After poking around with this for quite a bit, I've discovered that this is
not a problem because there is only one or proxy classes per service
created, not one or two proxy classes per thread. I had forgotten that
Hivemind instances a single outer proxy for all services, and that outer
proxy is handed out by the registry to all threads, and that the outer proxy
might actually instance the service object once per thread, but there is no
javassist enhancing going on for during object instancing for the
BuilderFactory.

You can prove this to your self with a simple program that get a thread
service and prints out the class name on different threads. The service can
act differently on each thread, but the registry always hands out the same
outer proxy instance.

On the other hand, if you have unreasonable registry with thousands of
services, there will be a memory build up in the ClassPool.

I apologize for sending out a somewhat alarming e-mail. I was hoping that
somebody who knew more would respond before I spent time disproving my
thesis.

Richard

-----Original Message-----
From: Hensley, Richard 
Sent: Thursday, May 19, 2005 10:38 AM
To: Hensley, Richard; 'hivemind-dev@jakarta.apache.org'
Subject: RE: Are threaded services building up CtClass instances in the
javassist ClassPool?

Here is a patch that at least shows that the CtClasses are hanging out in
the pool.

Index: framework/src/test/org/apache/hivemind/service/impl/TestClassFab.java
===================================================================
RCS file:
/home/cvspublic/jakarta-hivemind/framework/src/test/org/apache/hivemind/serv
ice/impl/TestClassFab.java,v
retrieving revision 1.5
diff -u -r1.5 TestClassFab.java
--- framework/src/test/org/apache/hivemind/service/impl/TestClassFab.java
6 Jan 2005 01:45:10 -0000       1.5
+++ framework/src/test/org/apache/hivemind/service/impl/TestClassFab.java
19 May 2005 17:31:17 -0000
@@ -27,11 +27,13 @@
 import java.util.zip.DataFormatException;
 
 import javassist.CtClass;
+import javassist.NotFoundException;
 import junit.framework.AssertionFailedError;
 
 import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.impl.BaseLocatable;
 import org.apache.hivemind.service.ClassFab;
+import org.apache.hivemind.service.ClassFabUtils;
 import org.apache.hivemind.service.MethodFab;
 import org.apache.hivemind.service.MethodSignature;
 import org.apache.hivemind.test.HiveMindTestCase;
@@ -46,6 +48,8 @@
 public class TestClassFab extends HiveMindTestCase
 {
     private CtClassSource _source;
+    
+    private HiveMindClassPool _pool;
 
     protected void setUp() throws Exception
     {
@@ -53,11 +57,11 @@
 
         ClassLoader threadLoader =
Thread.currentThread().getContextClassLoader();
 
-        HiveMindClassPool pool = new HiveMindClassPool();
+        _pool = new HiveMindClassPool();
 
-        pool.appendClassLoader(threadLoader);
+        _pool.appendClassLoader(threadLoader);
 
-        _source = new CtClassSource(pool);
+        _source = new CtClassSource(_pool);
     }
 
     private ClassFab newClassFab(String className, Class superClass)
@@ -67,6 +71,22 @@
         return new ClassFabImpl(_source, ctClass);
     }
 
+    public void testPoolBuildup() throws NotFoundException 
+    {
+        String firstGeneratedName = ClassFabUtils
+            .generateClassName(Runnable.class);
+        ClassFab cf = newClassFab(firstGeneratedName, Object.class);
+        cf.getClass();
+        try {
+            _pool.get(firstGeneratedName);
+            unreachable();
+        }
+        catch (NotFoundException ne) {
+            // expected
+        }
+    }
+
+    
     public void testCreateBean() throws Exception
     {
         ClassFab cf = newClassFab("TargetBean", Object.class); 

-----Original Message-----
From: Hensley, Richard 
Sent: Thursday, May 19, 2005 9:54 AM
To: 'hivemind-dev@jakarta.apache.org'
Subject: Are threaded services building up CtClass instances in the
javassist ClassPool?

I've been reviewing how javassist works, and a passage in the documentation
struck me as interesting. In short, it says that any CtClass created in the
javassist ClassPool stays in the pool forever. 

Now that got me thinking about how Hivemind uses javassist for threaded
services. If I read the code correctly, the TheadedServiceModel creates an
inner and outer proxy class with a unique name that implements the service
interface each time the service is instantiated. Upon reflection, I'm
wondering aloud if this is a potential memory leak. 

The specific thing that has me concerned is Tapestry 4.0 use of Thread
services for things like HttpServletRequest and HttpServletResponse. After
thousands of hits to the web application, would the javassist have a toxic
build up of CtClass instances?

If this is happening, it is a memory leak that could really cause a problem
for long running web applications.

I will see if I can prove or disprove my thesis later today.

There are good reasons for javassist keeping CtClass instances around,
however I'm not sure the reasons apply to Hivemind. We might be able to get
around a potential memory leak by simply detaching the Hivemind CtClass
instances from the javassist ClassPool after a class has been instantiated.
The CtClass instances are left in the pool so that future CtClass
manipulations can reference the new classes. I don't think Hivemind needs
this.

By the way, this would apply to the Singleton and Pooled models also, but
services using these models are long lived so new CtClasses are not created
very often for services that use these models.

I don't think this applies to the Primitive model.

Richard


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to