geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ke...@apache.org
Subject svn commit: r524358 - in /geronimo/server/trunk/modules/geronimo-persistence-jpa10: pom.xml src/main/java/org/apache/geronimo/persistence/PersistenceUnitGBean.java src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
Date Sat, 31 Mar 2007 03:18:01 GMT
Author: kevan
Date: Fri Mar 30 20:18:00 2007
New Revision: 524358

URL: http://svn.apache.org/viewvc?view=rev&rev=524358
Log:
GERONIMO-3053 Fix memory-related errors that can occur during multiple deploy/undeploy cycles.
Not actually a memory leak, per se. We were creating way more JarFiles than we should have
been. The number of JarFiles being created could have been reduced by a more effective (correct)
cloning algorithm. However, rather than cloning our ClassLoader DAG, we now use a TemporaryClassLoader
which reuses the existing ClassLoader DAG. TemporaryClassLoader comes from OpenEJB which got
it from OpenJPA...

Added:
    geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
  (with props)
Modified:
    geronimo/server/trunk/modules/geronimo-persistence-jpa10/pom.xml
    geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/PersistenceUnitGBean.java

Modified: geronimo/server/trunk/modules/geronimo-persistence-jpa10/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-persistence-jpa10/pom.xml?view=diff&rev=524358&r1=524357&r2=524358
==============================================================================
--- geronimo/server/trunk/modules/geronimo-persistence-jpa10/pom.xml (original)
+++ geronimo/server/trunk/modules/geronimo-persistence-jpa10/pom.xml Fri Mar 30 20:18:00 2007
@@ -35,6 +35,16 @@
 
     <dependencies>
 
+        <dependency>
+            <groupId>asm</groupId>
+            <artifactId>asm</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>asm</groupId>
+            <artifactId>asm-commons</artifactId>
+        </dependency>
+
         <!-- g-transaction, g-system come from this -->
         <dependency>
             <groupId>org.apache.geronimo.modules</groupId>

Modified: geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/PersistenceUnitGBean.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/PersistenceUnitGBean.java?view=diff&rev=524358&r1=524357&r2=524358
==============================================================================
--- geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/PersistenceUnitGBean.java
(original)
+++ geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/PersistenceUnitGBean.java
Fri Mar 30 20:18:00 2007
@@ -38,8 +38,8 @@
 import org.apache.geronimo.transaction.manager.TransactionManagerImpl;
 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
 import org.apache.geronimo.connector.outbound.ConnectionFactorySource;
+import org.apache.geronimo.persistence.TemporaryClassLoader;
 import org.apache.geronimo.transformer.TransformerAgent;
-import org.apache.geronimo.kernel.classloader.JarFileClassLoader;
 
 /**
  * @version $Rev$ $Date$
@@ -200,7 +200,7 @@
         private final boolean excludeUnlistedClassesValue;
         private final Properties properties;
         private final ClassLoader classLoader;
-        private final JarFileClassLoader tempClassLoader;
+        private final TemporaryClassLoader tempClassLoader;
         private final List<TransformerWrapper> transformers;
 
 
@@ -221,7 +221,7 @@
             
             // This classloader can only be used during PersistenceProvider.createContainerEntityManagerFactory()
calls
             // Possible that it could be cleaned up sooner, but for now it's destroyed when
the PUGBean is stopped
-            this.tempClassLoader = (JarFileClassLoader)JarFileClassLoader.copy(classLoader);

+            this.tempClassLoader = new TemporaryClassLoader(classLoader); 
         }
 
         public String getPersistenceUnitName() {
@@ -286,8 +286,6 @@
             for (TransformerWrapper t : transformers) {
                 TransformerAgent.removeTransformer(t);
             }
-
-            tempClassLoader.destroy();
         }
 
     }

Added: geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java?view=auto&rev=524358
==============================================================================
--- geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
(added)
+++ geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
Fri Mar 30 20:18:00 2007
@@ -0,0 +1,145 @@
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+package org.apache.geronimo.persistence;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLStreamHandlerFactory;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+* ClassLoader implementation that allows classes to be temporarily
+* loaded and then thrown away. Useful for verifying and inspecting
+* a class without first loading(and thus polluting) the parent
+* ClassLoader.
+* </p>
+* This class is a proper subclass of URLClassLoader.  This class
+* will locally load any class except for those defined in the
+* java.*, javax.* and sun.* packages and annotations all of which
+* are loaded by with
+* <code>Class.forName(name, resolve, getClass().getClassLoader())</code>
+* @author Marc Prud'hommeaux
+*/
+//Note: this class is a fork from OpenEJB which was a fork from OpenJPA
+public class TemporaryClassLoader extends URLClassLoader {
+   public TemporaryClassLoader(ClassLoader parent) {
+       super(new URL[0], parent);
+   }
+
+   public TemporaryClassLoader(URL[] urls, ClassLoader parent) {
+       super(urls, parent);
+   }
+
+   public TemporaryClassLoader(URL[] urls) {
+       super(urls);
+   }
+
+   public TemporaryClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory)
{
+       super(urls, parent, factory);
+   }
+
+   public Class loadClass(String name) throws ClassNotFoundException {
+       return loadClass(name, false);
+   }
+
+   protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException
{
+       // see if we've already loaded it
+       Class c = findLoadedClass(name);
+       if (c != null) {
+           return c;
+       }
+
+       // bug #283. defer to system if the name is a protected name.
+       // "sun." is required for JDK 1.4, which has an access check for
+       // sun.reflect.GeneratedSerializationConstructorAccessor1
+       if (name.startsWith("java.") ||
+               name.startsWith("javax.") ||
+               name.startsWith("sun.")) {
+           return Class.forName(name, resolve, getClass().getClassLoader());
+       }
+
+       String resourceName = name.replace('.', '/') + ".class";
+       InputStream in = getResourceAsStream(resourceName);
+       if (in == null) {
+           throw new ClassNotFoundException(name);
+       }
+
+       // 80% of class files are smaller then 6k
+       ByteArrayOutputStream bout = new ByteArrayOutputStream(8 * 1024);
+
+       // copy the input stream into a byte array
+       byte[] bytes = new byte[0];
+       try {
+           byte[] buf = new byte[4 * 1024];
+           for (int count = -1; (count = in.read(buf)) >= 0;) {
+               bout.write(buf, 0, count);
+           }
+           bytes = bout.toByteArray();
+       } catch (IOException e) {
+           throw new ClassNotFoundException(name, e);
+       }
+
+       // Annotation classes must be loaded by the normal classloader
+       if (isAnnotationClass(bytes)) {
+           return Class.forName(name, resolve, getClass().getClassLoader());
+       }
+
+       // define the package
+       int packageEndIndex = name.lastIndexOf('.');
+       if (packageEndIndex != -1) {
+           String packageName = name.substring(0, packageEndIndex);
+           if (getPackage(packageName) == null) {
+               definePackage(packageName, null, null, null, null, null, null, null);
+           }
+       }
+
+       // define the class
+       try {
+           return defineClass(name, bytes, 0, bytes.length);
+       } catch (SecurityException e) {
+           // possible prohibited package: defer to the parent
+           return super.loadClass(name, resolve);
+       }
+   }
+
+   /**
+    * Fast-parse the given class bytecode to determine if it is an
+    * annotation class.
+    */
+   private static boolean isAnnotationClass(byte[] bytes) {
+       IsAnnotationVisitor isAnnotationVisitor = new IsAnnotationVisitor();
+       ClassReader classReader = new ClassReader(bytes);
+       classReader.accept(isAnnotationVisitor, true);
+       return isAnnotationVisitor.isAnnotation;
+   }
+
+   public static class IsAnnotationVisitor extends EmptyVisitor {
+       public boolean isAnnotation = false;
+
+       public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
+           isAnnotation = (access & Opcodes.ACC_ANNOTATION) != 0;
+       }
+
+   }
+}
+

Propchange: geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/modules/geronimo-persistence-jpa10/src/main/java/org/apache/geronimo/persistence/TemporaryClassLoader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message