Discussion:
Classes generated on runtime (javassist) classloader issue
dkateros
2013-08-04 23:17:22 UTC
Permalink
Hello,

I stumbled on this issue while testing an application with the geronimo 3.01
release (currently runs on geronimo 2.2 for development and Websphere 8.5
for production).

This application creates concrete classes on runtime based on abstract
classes that exist on compile time.

Imagine the following scenario (extremely naive, but demonstrates the
issue).

public abstract class Foo { //exists on compile time
Set<String> strings; //package visible
}

public class FooConcreteEnhanced extends Foo { //generated on runtime
public FooConcreteEnhanced() { strings = new HashSet<String>(); }
}

When the app attempts to instantiate FooConcreteEnhanced, the following
error is thrown:

java.lang.IllegalAccessError: tried to access field pkg.Foo.strings from
class pkg.FooConcreteEnhanced

This might be caused if the runtime package of the classes is different,
which happens if the two classes are loaded by two different classloaders.
Changing the access modifier of strings to protected circumvents the
problem, but is not desirable, since a lot of the app's unit tests rely on
package visibility of fields.

Is there any configuration available that I might use to force the generated
classes to be loaded by the same class loader of the apps build time
classes?

PS: Note that the javassist.ClassPool instance that hosts the generated
classes is scoped on the jars of my application (as opposed to being scoped
on the default javassist ClassPool that might be loaded by a parent
classloader in case the application server loads the javassist library for
other reasons - like WebSphere 8.5 does).



--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097.html
Sent from the Users mailing list archive at Nabble.com.
Ivan
2013-08-05 13:59:03 UTC
Permalink
It is possible that javassist from the server side was used. Could you try
to use hidden-class in your geronimo-web.xml to prevent using javassist
from Geronimo server.

<*hidden*-*classes*><filter>javassist</filter></*hidden*-*classes*>

Hope it helps.
Post by dkateros
Hello,
I stumbled on this issue while testing an application with the geronimo 3.01
release (currently runs on geronimo 2.2 for development and Websphere 8.5
for production).
This application creates concrete classes on runtime based on abstract
classes that exist on compile time.
Imagine the following scenario (extremely naive, but demonstrates the
issue).
public abstract class Foo { //exists on compile time
Set<String> strings; //package visible
}
public class FooConcreteEnhanced extends Foo { //generated on runtime
public FooConcreteEnhanced() { strings = new HashSet<String>(); }
}
When the app attempts to instantiate FooConcreteEnhanced, the following
java.lang.IllegalAccessError: tried to access field pkg.Foo.strings from
class pkg.FooConcreteEnhanced
This might be caused if the runtime package of the classes is different,
which happens if the two classes are loaded by two different classloaders.
Changing the access modifier of strings to protected circumvents the
problem, but is not desirable, since a lot of the app's unit tests rely on
package visibility of fields.
Is there any configuration available that I might use to force the generated
classes to be loaded by the same class loader of the apps build time
classes?
PS: Note that the javassist.ClassPool instance that hosts the generated
classes is scoped on the jars of my application (as opposed to being scoped
on the default javassist ClassPool that might be loaded by a parent
classloader in case the application server loads the javassist library for
other reasons - like WebSphere 8.5 does).
--
http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097.html
Sent from the Users mailing list archive at Nabble.com.
--
Ivan
dkateros
2013-08-05 20:34:28 UTC
Permalink
Thank you for your reply Ivan.

When we migrated the app to WAS 8.5, we faced a problem that was caused by
this exact situation you describe: javassist was already loaded by the
parent classloader. We did not change that, instead we scoped the javassist
classpool singleton we use to create the runtime classes to our code (we
were using the default classpool before). Long story short the app runs now
on WAS 8.5 with the default "parent first" classloading policy.

However, your idea is quite good. I will try to hide the javassist.*
namespace from our app's classloader using the geronimo-web.xml
configuration you suggest and I will post my findings here.

It will take a few days (currently on vacation).

Regards // Dimitris



--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987102.html
Sent from the Users mailing list archive at Nabble.com.
dkateros
2013-08-12 10:13:02 UTC
Permalink
I tried Ivan's suggestion but the problem persists.

Any other suggestion would be most welcome at this point (even if it is to
submit a problem report).

TIA // Dimitris



--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987110.html
Sent from the Users mailing list archive at Nabble.com.
Ivan
2013-08-13 14:31:03 UTC
Permalink
Hmm, if you could provide a sample to reproduce this, I could take a look
at that in my local environment.
Post by dkateros
I tried Ivan's suggestion but the problem persists.
Any other suggestion would be most welcome at this point (even if it is to
submit a problem report).
TIA // Dimitris
--
http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987110.html
Sent from the Users mailing list archive at Nabble.com.
--
Ivan
dkateros
2013-08-14 12:19:36 UTC
Permalink
I created a standalone test case (depends only on java, servlet api and
javassist 3.9.0.GA.

You can download the war on the following URL (google drive)

https://docs.google.com/file/d/0BxXbVMAMFEYOWHJ3a09YRnE4N1U/edit?usp=sharing

On geronimo 2.2 the servlet GET method can be executed successfully as many
times as you like.

On geronimo 3.0.1 the first execution of the GET method throws the error I
have mentioned. I think it would be interesting to see what the second
execution does.

Regards // Dimitris



--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987116.html
Sent from the Users mailing list archive at Nabble.com.
Ivan
2013-08-16 01:08:47 UTC
Permalink
Thanks for the sample, I could reproduce this now, and will get back to you
in the next one or two days.
Post by dkateros
I created a standalone test case (depends only on java, servlet api and
javassist 3.9.0.GA.
You can download the war on the following URL (google drive)
https://docs.google.com/file/d/0BxXbVMAMFEYOWHJ3a09YRnE4N1U/edit?usp=sharing
On geronimo 2.2 the servlet GET method can be executed successfully as many
times as you like.
On geronimo 3.0.1 the first execution of the GET method throws the error I
have mentioned. I think it would be interesting to see what the second
execution does.
Regards // Dimitris
--
http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987116.html
Sent from the Users mailing list archive at Nabble.com.
--
Ivan
Ivan
2013-08-22 11:35:58 UTC
Permalink
Hi,
Sorry for the later response, was busy with other stuffs. Just create a
JIRA and attach a patched jar file, you may want to try that.

[1] https://issues.apache.org/jira/browse/GERONIMO-6488
Post by Ivan
Thanks for the sample, I could reproduce this now, and will get back to
you in the next one or two days.
Post by dkateros
I created a standalone test case (depends only on java, servlet api and
javassist 3.9.0.GA.
You can download the war on the following URL (google drive)
https://docs.google.com/file/d/0BxXbVMAMFEYOWHJ3a09YRnE4N1U/edit?usp=sharing
On geronimo 2.2 the servlet GET method can be executed successfully as many
times as you like.
On geronimo 3.0.1 the first execution of the GET method throws the error I
have mentioned. I think it would be interesting to see what the second
execution does.
Regards // Dimitris
--
http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987116.html
Sent from the Users mailing list archive at Nabble.com.
--
Ivan
--
Ivan
dkateros
2013-08-22 19:12:03 UTC
Permalink
Thank you very much Ivan, much appreciated.

I just tried the test case on my home setup, looks OK. I will confirm with
the actual application on work tomorrow (I actually got a weird error on the
work PC when I tried the patch earlier today, did you by any chance update
the patched jar file?). When I confirm everything is OK I will post here to
let you know that you can close the jira issue.

Once again, thank you.

Regards // Dimitris



--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987138.html
Sent from the Users mailing list archive at Nabble.com.
Ivan
2013-08-23 02:34:06 UTC
Permalink
Glad it works, I may come up some other following changes, mostly for jar
URL style while invoking getResources, will do that soon.
Post by dkateros
Thank you very much Ivan, much appreciated.
I just tried the test case on my home setup, looks OK. I will confirm with
the actual application on work tomorrow (I actually got a weird error on the
work PC when I tried the patch earlier today, did you by any chance update
the patched jar file?). When I confirm everything is OK I will post here to
let you know that you can close the jira issue.
Once again, thank you.
Regards // Dimitris
--
http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987138.html
Sent from the Users mailing list archive at Nabble.com.
--
Ivan
dkateros
2013-08-23 09:08:48 UTC
Permalink
Back to the work PC (the server is geronimo-tomcat7-javaee6-3.0.1 with a
couple test datasources set up).

The server boots up fine with the vanilla jar.

With the patched jar a "Main not found" message is printed in geronimo.out
after a minute or so (saw the other jira).

In the latter case I see an ERROR message in geronimo.log that is not
printed during normal start/stop with the vanilla jar.

2013-08-23 11:52:13,383 DEBUG [j2ee-system] FrameworkEvent ERROR
org.osgi.framework.BundleException: Exception in
org.apache.geronimo.system.osgi.BootActivator.start() of bundle
org.apache.geronimo.framework.j2ee-system.
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:734)
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
at
org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
at
org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:389)
at
org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1131)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:559)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:544)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:457)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:243)
at
org.eclipse.osgi.framework.internal.core.EquinoxLauncher.internalStart(EquinoxLauncher.java:271)
at
org.eclipse.osgi.framework.internal.core.EquinoxLauncher.start(EquinoxLauncher.java:241)
at org.eclipse.osgi.launch.Equinox.start(Equinox.java:258)
at
org.apache.geronimo.main.FrameworkLauncher.launchOSGiFramework(FrameworkLauncher.java:195)
at
org.apache.geronimo.main.FrameworkLauncher.launch(FrameworkLauncher.java:175)
at org.apache.geronimo.main.Bootstrapper.start(Bootstrapper.java:70)
at
org.apache.geronimo.main.Bootstrapper.execute(Bootstrapper.java:61)
at
org.apache.geronimo.cli.AbstractCLI.executeMain(AbstractCLI.java:65)
at org.apache.geronimo.cli.daemon.DaemonCLI.main(DaemonCLI.java:33)
Caused by: java.lang.NoClassDefFoundError:
org/osgi/framework/wiring/BundleWiring
at
org.apache.geronimo.gbean.runtime.GBeanInstance.<init>(GBeanInstance.java:252)
at
org.apache.geronimo.kernel.basic.BasicKernel.loadGBean(BasicKernel.java:361)
at
org.apache.geronimo.kernel.basic.BasicKernel.boot(BasicKernel.java:613)
at
org.apache.geronimo.system.osgi.BootActivator.start(BootActivator.java:58)
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
... 17 more
Caused by: java.lang.ClassNotFoundException:
org.osgi.framework.wiring.BundleWiring
at
org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:513)
at
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429)
at
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
at
org.apache.geronimo.hook.equinox.GeronimoClassLoader.loadClass(GeronimoClassLoader.java:85)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 24 more

In case this is not the culprit (looks like it), I can post the entire
startup log. Also, if you think that it has to do with the specific server
installation, I will happily unpack a fresh one, but I thought you might
want to take a peek.



--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987140.html
Sent from the Users mailing list archive at Nabble.com.
Ivan
2013-08-25 14:21:10 UTC
Permalink
Could you try to add the --clean option while starting the Geronimo server
? It looks like that the issue was caused by OSGi framework cache.
Post by dkateros
Back to the work PC (the server is geronimo-tomcat7-javaee6-3.0.1 with a
couple test datasources set up).
The server boots up fine with the vanilla jar.
With the patched jar a "Main not found" message is printed in geronimo.out
after a minute or so (saw the other jira).
In the latter case I see an ERROR message in geronimo.log that is not
printed during normal start/stop with the vanilla jar.
2013-08-23 11:52:13,383 DEBUG [j2ee-system] FrameworkEvent ERROR
org.osgi.framework.BundleException: Exception in
org.apache.geronimo.system.osgi.BootActivator.start() of bundle
org.apache.geronimo.framework.j2ee-system.
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:734)
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
at
org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
at
org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:389)
at
org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1131)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:559)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:544)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:457)
at
org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:243)
at
org.eclipse.osgi.framework.internal.core.EquinoxLauncher.internalStart(EquinoxLauncher.java:271)
at
org.eclipse.osgi.framework.internal.core.EquinoxLauncher.start(EquinoxLauncher.java:241)
at org.eclipse.osgi.launch.Equinox.start(Equinox.java:258)
at
org.apache.geronimo.main.FrameworkLauncher.launchOSGiFramework(FrameworkLauncher.java:195)
at
org.apache.geronimo.main.FrameworkLauncher.launch(FrameworkLauncher.java:175)
at
org.apache.geronimo.main.Bootstrapper.start(Bootstrapper.java:70)
at
org.apache.geronimo.main.Bootstrapper.execute(Bootstrapper.java:61)
at
org.apache.geronimo.cli.AbstractCLI.executeMain(AbstractCLI.java:65)
at org.apache.geronimo.cli.daemon.DaemonCLI.main(DaemonCLI.java:33)
org/osgi/framework/wiring/BundleWiring
at
org.apache.geronimo.gbean.runtime.GBeanInstance.<init>(GBeanInstance.java:252)
at
org.apache.geronimo.kernel.basic.BasicKernel.loadGBean(BasicKernel.java:361)
at
org.apache.geronimo.kernel.basic.BasicKernel.boot(BasicKernel.java:613)
at
org.apache.geronimo.system.osgi.BootActivator.start(BootActivator.java:58)
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at
org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
... 17 more
org.osgi.framework.wiring.BundleWiring
at
org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:513)
at
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429)
at
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
at
org.apache.geronimo.hook.equinox.GeronimoClassLoader.loadClass(GeronimoClassLoader.java:85)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 24 more
In case this is not the culprit (looks like it), I can post the entire
startup log. Also, if you think that it has to do with the specific server
installation, I will happily unpack a fresh one, but I thought you might
want to take a peek.
--
http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987140.html
Sent from the Users mailing list archive at Nabble.com.
--
Ivan
dkateros
2013-08-27 08:48:18 UTC
Permalink
That one did the trick. Everything seems to be OK now. Thank you for your
assistance.



--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3987143.html
Sent from the Users mailing list archive at Nabble.com.
dkateros
2014-09-15 08:38:59 UTC
Permalink
12 something months later, I revisited this. Turns out that it is possible,
after all, to have javassist load the generated class to the classloader of
the abstract class that the generated class extends. Oh, well.




--
View this message in context: http://apache-geronimo.328035.n3.nabble.com/Classes-generated-on-runtime-javassist-classloader-issue-tp3987097p3988284.html
Sent from the Users mailing list archive at Nabble.com.

Loading...