views:

418

answers:

4

I have a Hibernate Entity:

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

My VM is configured with a maximum heap size of 512 MB. When I try to persist an object which has a 75 MB large object, I get an OutOfMemoryError.

The names of the methods in the stack trace (StringBuilder, ByteArrayBlobType.toLoggableString, pretty.Printer.toString) suggest that hibernate is trying to write a very large log message that contains my object.

Am I correct about why hibernate is using so much memory? What is the simplest way to work around this problem?

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)
A: 

The first test is to see if it really is a logging issue. What logger are you using? If it's log4j, then you can try to turn off all logging from Hibernate with the following line in your log4j.properties file:

log4j.logger.org.hibernate=OFF

That might not be the ultimate, ideal way for your app to operate, but it might help you test whether logging is the issue.

delfuego
@delfuego: Thanks for the tip about how to disable it. I created an empty file in the root of my classpath and added that line to it, and I'm still getting a lot of messages that come from hibernate in the console, for example:12:44:42,530 INFO [STDOUT] Hibernate: /* select o from Permission o */ select permission0_.id as id21_, permission0_I will go look for some info about how to disable logging, since this isn't working for me.
paul
A: 

The pretty printer is probably converting the bytes to hex notation (e.g. '0x55 0xF3 ...)', so for each byte in the blob you get 4 bytes of output so 300M of output, that and buffering, with other stuff in your VM probably puts you over the limit.

Justin
That's what I am thinking. Now I just need to know how to turn that "feature" off. :)
paul
How about the Hibernate properties hibernate.show_sql=false and hibernate.format_sql=false ?
opyate
A: 

I solved the problem. Turning off logging did fix the problem, but I didn't understand that when running under the JBoss application server, the server's own log4j.xml file overrides whatever I put the in classpath of the application.

I opened up /jboss-4.2.3.GA/server/default/conf/log4.xml, and inserted this:

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

This fixes the issue I am seeing.

paul
A: 

What if you try the following two Hibernate properties?

hibernate.show_sql=false
hibernate.format_sql=false
opyate