OutOfMemoryError & setString

thesecondwoodstock 2002-06-03 09:59:27
1.我在编写一个Java Application的时候,运行时遇到一个OutOfMemoryError错误(printStack是空的),然后程序就终止了。好像不是每次都这样。这是怎么回事呢?
2.PrepareStatement的setString会把java的内部数据类型(String)转为SQL的varchar类型是吗?我用oracle数据库,一个表中的某个字段是varchar2(2048),在程序中用setString时原以为可以判断String的length是否超过2048,若超过就在程序中截取再调setString,但是发现实际运行时还是报SQL错,说插入时字符长度超过2048了。如果判断length是否超过256就不会有问题,这和unicode有关吗?
...全文
60 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
to maoxuguang:
谢谢,如何理解"需要用JDBC的Long类型来操作",能否再详细些。
to haichuang:
如果是这个原因,好像还是不对,我曾经这样解释过,但是“膨胀”的倍数不是2倍,而是3.X倍,如果字串内容不一样,倍数还不是一个常量。
haichuang 2002-06-03
  • 打赏
  • 举报
回复
第一个问题是一个内存溢出错误,但具体原因就很难说,这个可能关系到JAVA的一些数据处理的长度问题,你可以检查一下程序,看看数据类型是不是使用正确,有没有在运行时会超出该类型所能表示长度的可能等等.
haichuang 2002-06-03
  • 打赏
  • 举报
回复
应该是编码转换时导致在JAVA中的字符串长度与数据库中的长度不一样造成的. 因为在JAVA中是采用UNICODE编码,因此如果有中文的话他仍会计为一个字符,但在ORACLE中一个中文字符是占两个字符位的,所以,在你的数据库中如果要插入中文的话,最好长度设为你欲限定长度的2倍.
maoxuguang 2002-06-03
  • 打赏
  • 举报
回复
问题1:
OutOfMemoryError是一个内存溢出Error、不是Excepion,你可以通过
try {
...
} catch (Error e) {
..
}
捕获到它。
出现这个错误的原因:新的对象需要空间,而JVM回收没用对象的速度不够快,又没有来得及申请更多的空间;或者程序中积累了太多的对象。两者都是程序编写的问题。

问题2
即使是varchar2类型,有时也不能简单的用setString来完成插入操作,用JDBC的setString是有长度限制的。如果字符很长,就需要用JDBC的Long类型来操作。不知道这时不是你遇到的问题。
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
to wyalchemy:
sorry,刚才是笔误,应该是"length()是对的",而非"length() - 1是对的"
不理解你的意思。
对于问题2,我现在是采用“过份”减少字符长度的方法来解决的,程序运行很好,没有sql异常出现。
虽然问题是解决了,但是我还是不明白问题产生的原因,所以才会问的。
wyalchemy 2002-06-03
  • 打赏
  • 举报
回复
是的,我测试了下面的代码:

String s = "0123456789";
StringBuffer strbufTemp = new StringBuffer(s);
if( 6 < strbufTemp.length()){
strbufTemp.delete(6,strbufTemp.length());
System.out.println("s: " + s);
System.out.println("strbufTemp: " + strbufTemp);

}
得到的结果是:
s: 0123456789
strbufTemp: 012345
///////////////////
对于“
可是现在是,如果如我所写的那样运行,就不会有sql异常了(因为已经截取的很短了),

那我想是你的if条件有问题了吧,试试这样:
if (strbuf.length() >= 600)
或:
if (600 < strbuf.length() ) // 一般这样写。
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
to wyalchemy:
我相信这句没有写错,你是觉得delete没有正确操作,导致strbuf还是原来的长度?
可是现在是,如果如我所写的那样运行,就不会有sql异常了(因为已经截取的很短了),不信可以用length方法验证。length() - 1是对的(end - The ending index, exclusive.)
wyalchemy 2002-06-03
  • 打赏
  • 举报
回复
如果还不行,看看:
strbuf.delete(599, strbuf.length()-1);
//strbuf.delete(600-1, strbuf.length()-1);

thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
对于问题1:
某次错误打印结果:
Exception in thread "main" java.lang.OutOfMemoryError
<<no stack trace available>>

我还没有定位过程序在什么地方才出这个错,但似乎不太好定位,如果是一般的exception,它会告诉你哪个java文件的哪行,直接去那里找就可以了。

to wyalchemy:
这句应该没有写错吧,jdk1.3的onlinehelp:
public StringBuffer delete(int start,
int end)


Removes the characters in a substring of this StringBuffer. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the StringBuffer if no such character exists. If start is equal to end, no changes are made.

Parameters:

start - The beginning index, inclusive.
end - The ending index, exclusive.

Returns:

This string buffer.

Throws:

StringIndexOutOfBoundsException - if start is negative, greater than length(), or greater than end.

Since:

1.2
wyalchemy 2002-06-03
  • 打赏
  • 举报
回复
除了最好用 new version of oracle jdbc driver 外,你的:
strbuf.delete(600, strbuf.length());
这句写错了,应该是:
strbuf.delete(600, strbuf.length()-1);
试一试看看!
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
能否具体一些,我用的是oracle8i,应该没有问题吧,而且以前好像从来都没有遇到过类似情况,问了一些朋友,也都说没有遇到类似情况。我猜想应该是setString在处理时做了转换并产生了"膨胀"现象,java的字符串到sql的varchar2是如何转换的呢?和unicode的关系又是怎样的呢?
skyyoung 2002-06-03
  • 打赏
  • 举报
回复
use new version of oracle jdbc driver.
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
对于问题2:
在程序中的某处判断(原来是2048,不是600)
if (strbuf.length() > 600)
strbuf.delete(600, strbuf.length());

另一处
String sql = "insert into CONTENT_TABLE"
+ "(CONTENT_ID,TITLE,CONTENT,CREATE_DATE) "
+ "values(" + CONTENT_SEQUENCE.NEXTVAL,?,?,SYSDATE)";
PreparedStatement ps = codb.getPreparedStatement(sql);
ps.setString(1, "Title"); // 没问题因为字符串短
ps.setString(2, strbuf); // 有时有问题,因为长
ps.executeUpdate();
ps.close();

某次打印错误结果:
Error:java.sql.SQLException: Error in insertAfterCopy into CONTENT_TABLE:java.sql.SQLException: 数据大小超出此类型的最大值: 2254
wyalchemy 2002-06-03
  • 打赏
  • 举报
回复
?当然是分别都贴出来了,来看你帖子的又不止我一个,提多些相关内容总是有利于问题的解决呀!
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
你指的是1还是2?
wyalchemy 2002-06-03
  • 打赏
  • 举报
回复
按理说应该不会有你说的情况出现,贴写相关的东西出来看看再说?
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
谢谢 maoxuguang,
谢谢 wyalchemy
maoxuguang 2002-06-03
  • 打赏
  • 举报
回复
1.Orcale中存储字符也使用是unicode,不会存在编码问题.
2.JVM内存空间在其启动可以通过参数设定,但根据运行情况会不断的申请或释放内存,很难控制。在一个简单的Application中出现这个问题,最好还是检查一下你的代码,看一看是否有可能有隐含的指向无用对象的句柄或者输入的数据可能过大。
3.wyalchemy的建议也有道理,JDBC的Driver和数据库要保持同样的版本,尤其是Oracle.
4.对于比较长的字符串,使用setLong和getLong,象LOB类型一样进行流操作,使用方法可以你看一看JDK API文档。用setString或getString写或读出的字符有限制(大小忘记了)。
thesecondwoodstock 2002-06-03
  • 打赏
  • 举报
回复
看起来,第二个问题,大概可以有一个简单的解释了。只是还有些模糊,setString这个东东到底做了些什么。
对于第一个问题,我想maoxuguang的解释比较符合我的情况。但是除了我能够catch之外,似乎找不到别的解决方法了。JVM的内存使用空间是否可以设置?
wyalchemy 2002-06-03
  • 打赏
  • 举报
回复
是的:
应该是"length()是对的",
///////////////////////////
问题产生的原因就是“你所用的oracle jdbc driver 的setString是有长度限制的”
所以建议你还是 用 new version of oracle jdbc driver 的好,
另外,
如果你确实需要较大的长度,不妨数据库字段用LONG或大字段BLOB。
对于LONG ,应该要保证你的一个表里只有一列为LONG型,可以用setString(),和getString() 方法来操作。
对于BLOB 则用流来操作。

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧