[hibernate-commits] Hibernate SVN: r11296 - in branches/Branch_3_2/Hibernate3: test/org/hibernate/test/bytecode and 1 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Sun Mar 18 00:10:10 EDT 2007
Author: scottmarlownovell
Date: 2007-03-18 00:10:09 -0400 (Sun, 18 Mar 2007)
New Revision: 11296
Added:
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/ProxyBean.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/cglib/CGLIBThreadLocalTest.java
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/Bean.hbm.xml
branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/BytecodeSuite.java
Log:
HHH-2481 Fix memory leak.
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2007-03-18 04:05:28 UTC (rev 11295)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java 2007-03-18 04:10:09 UTC (rev 11296)
@@ -60,8 +60,7 @@
final HibernateProxy proxy;
Class factory = getProxyFactory(persistentClass, interfaces);
- Enhancer.registerCallbacks(factory, new Callback[]{ instance, null });
- proxy = (HibernateProxy)factory.newInstance();
+ proxy = getProxyInstance(factory, instance);
instance.constructed = true;
return proxy;
}
@@ -91,8 +90,7 @@
final HibernateProxy proxy;
try {
- Enhancer.registerCallbacks(factory, new Callback[]{ instance, null });
- proxy = (HibernateProxy) factory.newInstance();
+ proxy = getProxyInstance(factory, instance);
}
catch (Exception e) {
throw new HibernateException( "CGLIB Enhancement failed: " + persistentClass.getName(), e );
@@ -102,7 +100,19 @@
return proxy;
}
- public static Class getProxyFactory(Class persistentClass, Class[] interfaces)
+ private static HibernateProxy getProxyInstance(Class factory, CGLIBLazyInitializer instance) throws InstantiationException, IllegalAccessException {
+ HibernateProxy proxy;
+ try {
+ Enhancer.registerCallbacks(factory, new Callback[]{ instance, null });
+ proxy = (HibernateProxy)factory.newInstance();
+ } finally {
+ // HHH-2481 make sure the callback gets cleared, otherwise the instance stays in a static thread local.
+ Enhancer.registerCallbacks(factory, null);
+ }
+ return proxy;
+ }
+
+ public static Class getProxyFactory(Class persistentClass, Class[] interfaces)
throws HibernateException {
Enhancer e = new Enhancer();
e.setSuperclass( interfaces.length == 1 ? persistentClass : null );
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/Bean.hbm.xml
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/Bean.hbm.xml 2007-03-18 04:05:28 UTC (rev 11295)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/Bean.hbm.xml 2007-03-18 04:10:09 UTC (rev 11296)
@@ -17,4 +17,12 @@
<property name="someObject" type="serializable" column="S_OBJ_1" />
</class>
+
+ <class name="ProxyBean" lazy="true">
+ <id name="someString" type="string">
+ <generator class="assigned"/>
+ </id>
+ <property name="someLong" type="long" column="S_LONG_1" />
+ </class>
+
</hibernate-mapping>
Modified: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/BytecodeSuite.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/BytecodeSuite.java 2007-03-18 04:05:28 UTC (rev 11295)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/BytecodeSuite.java 2007-03-18 04:10:09 UTC (rev 11296)
@@ -13,6 +13,7 @@
TestSuite suite = new TestSuite( "BytecodeProvider tests" );
suite.addTest( org.hibernate.test.bytecode.cglib.ReflectionOptimizerTest.suite() );
suite.addTest( org.hibernate.test.bytecode.cglib.InvocationTargetExceptionTest.suite() );
+ suite.addTest( org.hibernate.test.bytecode.cglib.CGLIBThreadLocalTest.suite() );
suite.addTest( org.hibernate.test.bytecode.javassist.ReflectionOptimizerTest.suite() );
suite.addTest( org.hibernate.test.bytecode.javassist.InvocationTargetExceptionTest.suite() );
return suite;
Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/ProxyBean.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/ProxyBean.java (rev 0)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/ProxyBean.java 2007-03-18 04:10:09 UTC (rev 11296)
@@ -0,0 +1,31 @@
+package org.hibernate.test.bytecode;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: Paul
+ * Date: Mar 9, 2007
+ * Time: 11:31:40 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ProxyBean {
+ private String someString;
+ private long someLong;
+
+
+ public String getSomeString() {
+ return someString;
+ }
+
+ public void setSomeString(String someString) {
+ this.someString = someString;
+ }
+
+
+ public long getSomeLong() {
+ return someLong;
+ }
+
+ public void setSomeLong(long someLong) {
+ this.someLong = someLong;
+ }
+}
Added: branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/cglib/CGLIBThreadLocalTest.java
===================================================================
--- branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/cglib/CGLIBThreadLocalTest.java (rev 0)
+++ branches/Branch_3_2/Hibernate3/test/org/hibernate/test/bytecode/cglib/CGLIBThreadLocalTest.java 2007-03-18 04:10:09 UTC (rev 11296)
@@ -0,0 +1,73 @@
+package org.hibernate.test.bytecode.cglib;
+
+import org.hibernate.junit.functional.*;
+import org.hibernate.cfg.*;
+import org.hibernate.*;
+import org.hibernate.proxy.*;
+import org.hibernate.test.bytecode.*;
+import junit.framework.*;
+
+import java.text.*;
+import java.lang.reflect.*;
+
+import net.sf.cglib.proxy.*;
+
+/**
+ * Test that the static thread local callback object is cleared out of the proxy class after instantiated.
+ * This tests that the memory leak reported by HHH-2481 hasn't been re-introduced.
+ *
+ * @author Paul Malolepsy
+ */
+public class CGLIBThreadLocalTest extends FunctionalTestCase {
+ public CGLIBThreadLocalTest(String name) {
+ super(name);
+ }
+
+ public String[] getMappings() {
+ return new String[]{"bytecode/Bean.hbm.xml"};
+ }
+
+ public static TestSuite suite() {
+ return new FunctionalTestClassTestSuite(CGLIBThreadLocalTest.class);
+ }
+
+ public void testCglibClearing() {
+ if (!(Environment.getBytecodeProvider() instanceof org.hibernate.bytecode.cglib.BytecodeProviderImpl)) {
+ // because of the scoping :(
+ reportSkip("env not configured for cglib provider", "cglib thread local callback clearing");
+ return;
+ }
+
+ //create the object for the test
+ Session s = openSession();
+ s.beginTransaction();
+ ProxyBean proxyBean = new ProxyBean();
+ proxyBean.setSomeString("my-bean");
+ proxyBean.setSomeLong(1234);
+ s.save(proxyBean);
+ s.getTransaction().commit();
+ s.close();
+
+ // read the object as a proxy
+ s = openSession();
+ s.beginTransaction();
+ proxyBean = (ProxyBean) s.load(ProxyBean.class, proxyBean.getSomeString());
+ assertTrue(proxyBean instanceof HibernateProxy);
+ try {
+ //check that the static thread callbacks thread local has been cleared out
+ Field field = proxyBean.getClass().getDeclaredField("CGLIB$THREAD_CALLBACKS");
+ field.setAccessible(true);
+ ThreadLocal threadCallbacksThreadLocal = (ThreadLocal) field.get(null);
+ assertTrue(threadCallbacksThreadLocal.get() == null);
+ } catch (NoSuchFieldException e1) {
+ fail("unable to find CGLIB$THREAD_CALLBACKS field in proxy.");
+ } catch (Throwable t) {
+ fail("unexpected exception type : " + t);
+ } finally {
+ //clean up
+ s.delete(proxyBean);
+ s.getTransaction().commit();
+ s.close();
+ }
+ }
+}
More information about the hibernate-commits
mailing list