Hibernate:OutOfMemoryError在打印日志消息时持久保存Blob

时间:2009-11-17 17:31:58

标签: hibernate blob stringbuilder pretty-print out-of-memory

我有一个Hibernate实体:

@Entity
class Foo {
    //...
    @Lob
    public byte[] getBytes() { return bytes; }
    //....
}

我的VM配置的最大堆大小为512 MB。当我尝试持久化具有75 MB大对象的对象时,我得到一个OutOfMemoryError。

堆栈跟踪中的方法名称(StringBuilder,ByteArrayBlobType.toLoggableString,pretty.Printer.toString)表明hibernate正在尝试编写包含我的对象的非常大的日志消息。

我是否正确了解为什么hibernate使用了这么多内存?解决这个问题最简单的方法是什么?

java.lang.OutOfMemoryError: Java heap space
at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:44)
at java.lang.StringBuilder.<init>(StringBuilder.java:81)
at org.hibernate.type.ByteArrayBlobType.toString(ByteArrayBlobType.java:117)
at org.hibernate.type.ByteArrayBlobType.toLoggableString(ByteArrayBlobType.java:127)
at org.hibernate.pretty.Printer.toString(Printer.java:53)
at org.hibernate.pretty.Printer.toString(Printer.java:90)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:97)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.jboss.seam.persistence.HibernateSessionProxy.flush(HibernateSessionProxy.java:181)

4 个答案:

答案 0 :(得分:3)

我解决了这个问题。关闭日志记录确实解决了问题,但我不明白在JBoss应用程序服务器下运行时,服务器自己的log4j.xml文件会覆盖我在应用程序的类路径中放置的任何内容。

我打开了/jboss-4.2.3.GA/server/default/conf/log4.xml,插入了这个:

<category name="org.hibernate">
    <priority value="ERROR"/>
</category>

这解决了我所看到的问题。

答案 1 :(得分:0)

第一个测试是看它是否真的是一个日志记录问题。你用什么记录器?如果它是log4j,那么您可以尝试使用log4j.properties文件中的以下行关闭来自Hibernate的所有日志记录:

  

log4j.logger.org.hibernate = OFF

这可能不是您的应用运行的最佳,理想的方式,但它可能会帮助您测试日志记录是否是问题。

答案 2 :(得分:0)

漂亮的打印机可能会将字节转换为十六进制表示法(例如'0x55 0xF3 ...)',因此对于blob中的每个字节,您将获得4个字节的输出,因此300M的输出,即缓冲和其他内容在您的虚拟机中可能会超出限制。

答案 3 :(得分:0)

如果您尝试以下两个Hibernate属性怎么办?

hibernate.show_sql=false
hibernate.format_sql=false