Author: niallp
Date: Thu Aug 28 07:12:13 2008
New Revision: 689831

URL: http://svn.apache.org/viewvc?rev=689831&view=rev
Log:
BEANUTILS-291 - Re-create class reference if lost - fixes problem on JRockit 
JDK - thanks to Jörg Schaible

Modified:
    
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java
    
commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/memoryleaktests/MemoryLeakTestCase.java

Modified: 
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java
URL: 
http://svn.apache.org/viewvc/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java?rev=689831&r1=689830&r2=689831&view=diff
==============================================================================
--- 
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java
 (original)
+++ 
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/MappedPropertyDescriptor.java
 Thu Aug 28 07:12:13 2008
@@ -452,6 +452,12 @@
             if (m == null) {
                 Class clazz = (Class)classRef.get();
                 if (clazz == null) {
+                    clazz = reLoadClass();
+                    if (clazz != null) {
+                        classRef = new WeakReference(clazz);
+                    }
+                }
+                if (clazz == null) {
                     throw new RuntimeException("Method " + methodName + " for 
" +
                             className + " could not be reconstructed - class 
reference has gone");
                 }
@@ -473,5 +479,29 @@
             }
             return m;
         }
+
+        /**
+         * Try to re-load the class
+         */
+        private Class reLoadClass() {
+
+            ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+
+            // Try the context class loader
+            if (classLoader != null) {
+                try {
+                    return classLoader.loadClass(className);
+                } catch (Throwable t) {
+                    // ignore
+                }
+            }
+
+            // Try this class's class loader
+            try {
+                return classLoader.loadClass(className);
+            } catch (Throwable t) {
+                return null;
+            }
+        }
     }
 }

Modified: 
commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/memoryleaktests/MemoryLeakTestCase.java
URL: 
http://svn.apache.org/viewvc/commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/memoryleaktests/MemoryLeakTestCase.java?rev=689831&r1=689830&r2=689831&view=diff
==============================================================================
--- 
commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/memoryleaktests/MemoryLeakTestCase.java
 (original)
+++ 
commons/proper/beanutils/trunk/src/test/org/apache/commons/beanutils/memoryleaktests/MemoryLeakTestCase.java
 Thu Aug 28 07:12:13 2008
@@ -155,7 +155,7 @@
      * Tests that MappedPropertyDescriptor can re-create the Method reference 
after it
      * has been garbage collected.
      */
-    public void testMappedPropertyDescriptor_MappedMethodReference() throws 
Exception {
+    public void testMappedPropertyDescriptor_MappedMethodReference1() throws 
Exception {
 
         // Clear All BeanUtils caches before the test
         clearAllBeanUtilsCaches();
@@ -196,6 +196,55 @@
     }
 
     /**
+     * Tests that MappedPropertyDescriptor can re-create the Method reference 
after it
+     * has been garbage collected.
+     */
+    public void testMappedPropertyDescriptor_MappedMethodReference2() throws 
Exception {
+
+        // Clear All BeanUtils caches before the test
+        clearAllBeanUtilsCaches();
+
+        String className = 
"org.apache.commons.beanutils.memoryleaktests.pojotests.SomeMappedPojo";
+        ClassLoader loader = newClassLoader();
+        Class beanClass    = loader.loadClass(className);
+        Object bean        = beanClass.newInstance();
+        // 
-----------------------------------------------------------------------------
+
+        // Sanity checks only
+        assertNotNull("ClassLoader is null", loader);
+        assertNotNull("BeanClass is null", beanClass);
+        assertNotSame("ClassLoaders should be different..", 
getClass().getClassLoader(), beanClass.getClassLoader());
+        assertSame("BeanClass ClassLoader incorrect", 
beanClass.getClassLoader(), loader);
+
+        MappedPropertyDescriptor descriptor = new 
MappedPropertyDescriptor("mappedProperty", beanClass);
+        assertNotNull("1-Read Method null", descriptor.getMappedReadMethod());
+        assertNotNull("1-Write Method null", 
descriptor.getMappedWriteMethod());
+        assertEquals("1-Read Method name", "getMappedProperty", 
descriptor.getMappedReadMethod().getName());
+        assertEquals("1-Read Write name", "setMappedProperty", 
descriptor.getMappedWriteMethod().getName());
+
+        // this should make the reference go away.
+        loader = null;
+        beanClass = null;
+        bean = null;
+
+        forceGarbageCollection(); /* Try to force the garbage collector to run 
by filling up memory */
+
+        // The aim of this test is to check the functinality in 
MappedPropertyDescriptor which
+        // re-creates the Method references after they have been garbage 
collected. However theres no
+        // way of knowing the method references were garbage collected and 
that code was run, except by
+        // un-commeting the System.out statement in MappedPropertyDescriptor's 
MappedMethodReference's
+        // get() method.
+
+        assertNotNull("1-Read Method null", descriptor.getMappedReadMethod());
+        assertNotNull("1-Write Method null", 
descriptor.getMappedWriteMethod());
+        assertEquals("1-Read Method name", "getMappedProperty", 
descriptor.getMappedReadMethod().getName());
+        assertEquals("1-Read Write name", "setMappedProperty", 
descriptor.getMappedWriteMethod().getName());
+
+        // Clear All BeanUtils caches after the test
+        clearAllBeanUtilsCaches();
+    }
+
+    /**
      * Tests that MethodUtils's cache doesn't cause a memory leak.
      */
     public void testMethodUtils_cache_memoryLeak() throws Exception {


Reply via email to