[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