Can't instantiate anonymous class more than 16 times
Wei Yin Teo
weiyinteo at gmail.com
Mon Aug 10 15:49:40 PDT 2009
Right, I think the work around is working because we are getting a new
class and we don't hit the threshold.
The magic number 15 is the ReflectionFactory.inflationThreshold() as
we can see in the class NativeConstructorAccessorImpl
public Object newInstance(Object[] args) ... {
if (++numInvocations >
ReflectionFactory.inflationThreshold()) {
ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
new MethodAccessorGenerator().
generateConstructor(...)
...
I think the AnonymousClassLoader mangles the class name from
InstanceTest to InstanceTest/123456. However the generated
ConstructorAccessor would interpret that as a class InstanceTest.
123456 instead of InstanceTest and the JVM would then try to load
InstanceTest/123456.class. Of course it can't be found anywhere. I
suppose Class.forName() should not be able to locate it in the
system(permGen?) name space, either.
On further note, I can't load an anonymous class which subclass
another anonymous class too; because the class loader can't find the
super class. I am not too sure about how the class loading mechanism
plays with anonymous classes, especially how do we maintain an
anonymous class hierarchy.
Thanks,
Wei
On 10 Aug 2009, at 23:19, Rémi Forax wrote:
> Le 10/08/2009 23:54, Rémi Forax a écrit :
>>
>> Le 10/08/2009 21:56, Wei Yin Teo a écrit :
>>>
>>> Hi,
>>>
>>> After loading an anonymous class through the AnonymousClassLoader,
>>> I could construct the object by calling the newInstance on the
>>> class. But the 16th time failed. Here is the code and stack trace
>>
>> hum, perhaps a bug,
>> could you try with :
>>
>> AnonymousClassLoader acl = new
>> AnonymousClassLoader(LoadingTest.class);
>>
>> cheers,
>> Rémi
>
> Forget what I've written.
> I am able to reproduce the bug.
> It seems you can't create more than 16 instances of an anonymous
> class,
> a really weird bug, isn't it.
>
> The known workaround is to create one class by instance :(
>
> ...
> byte[] classBytes = getClassBytes();
> for (int i = 0; i < 100; i++) {
> Class<?> testClass = acl.loadClass(classBytes);
> try {
> testClass.newInstance();
> }
> ...
>
> Rémi
>
>>
>>>
>>> class LoadingTest {
>>>
>>> public void testLoading() {
>>> AnonymousClassLoader acl = new AnonymousClassLoader();
>>>
>>> Class<?> testClass = acl.loadClass(getClassBytes());
>>>
>>> for (int i = 0; i < 100; i++) {
>>> try {
>>> testClass.newInstance();
>>> }
>>> catch(Throwable e) {
>>> System.out.println("failed at " + i);
>>> e.printStackTrace();
>>> throw e;
>>> }
>>> }
>>> }
>>>
>>> private byte[] getClassBytes() {
>>> ClassWriter cw = new ClassWriter(0);
>>> MethodVisitor mv;
>>>
>>> cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "InstanceTest", null,
>>> "java/lang/Object", null);
>>> mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
>>> mv.visitCode();
>>> Label l0 = new Label();
>>> mv.visitLabel(l0);
>>> mv.visitVarInsn(ALOAD, 0);
>>> mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>",
>>> "()V");
>>> mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
>>> "Ljava/io/PrintStream;");
>>> mv.visitLdcInsn("constructed");
>>> mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
>>> "(Ljava/lang/String;)V");
>>> mv.visitInsn(RETURN);
>>> Label l1 = new Label();
>>> mv.visitLabel(l1);
>>> mv
>>> .visitLocalVariable("this",
>>> "Ltest/com/gs/s4j/misc/AnonymousClassLoading;", null,
>>> l0, l1, 0);
>>> mv.visitMaxs(2, 1);
>>> mv.visitEnd();
>>> cw.visitEnd();
>>> return cw.toByteArray():
>>> }
>>> }
>>>
>>> It appears at the 16th time, the JVM generate a
>>> ConstructorAccessor and it does not know how to handle anonymous
>>> class.
>>>
>>> Thanks,
>>> Wei
>>>
>>> Here is the output from the code.
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> =
>>> ====================================================================
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> constructed
>>> failed at 16
>>> java.lang.NoClassDefFoundError: InstanceTest/7572081
>>> at sun.reflect.GeneratedConstructorAccessor3.newInstance(Unknown
>>> Source)
>>> at
>>> sun
>>> .reflect
>>> .DelegatingConstructorAccessorImpl
>>> .newInstance(DelegatingConstructorAccessorImpl.java:45)
>>> at java.lang.reflect.Constructor.newInstance(Constructor.java:539)
>>> at java.lang.Class.newInstance0(Class.java:372)
>>> at java.lang.Class.newInstance(Class.java:325)
>>> at
>>> test
>>> .com
>>> .gs
>>> .s4j
>>> .misc.AnonymousClassLoading.testLoading(AnonymousClassLoading.java:
>>> 47)
>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>> at
>>> sun
>>> .reflect
>>> .NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>> at
>>> sun
>>> .reflect
>>> .DelegatingMethodAccessorImpl
>>> .invoke(DelegatingMethodAccessorImpl.java:43)
>>> at java.lang.reflect.Method.invoke(Method.java:623)
>>> at junit.framework.TestCase.runTest(TestCase.java:164)
>>> at junit.framework.TestCase.runBare(TestCase.java:130)
>>> at junit.framework.TestResult$1.protect(TestResult.java:106)
>>> at junit.framework.TestResult.runProtected(TestResult.java:124)
>>> at junit.framework.TestResult.run(TestResult.java:109)
>>> at junit.framework.TestCase.run(TestCase.java:120)
>>> at
>>> org
>>> .eclipse
>>> .jdt
>>> .internal
>>> .junit
>>> .runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
>>> at
>>> org
>>> .eclipse
>>> .jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
>>> at
>>> org
>>> .eclipse
>>> .jdt
>>> .internal
>>> .junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
>>> at
>>> org
>>> .eclipse
>>> .jdt
>>> .internal
>>> .junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
>>> at
>>> org
>>> .eclipse
>>> .jdt
>>> .internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:
>>> 390)
>>> at
>>> org
>>> .eclipse
>>> .pde
>>> .internal
>>> .junit
>>> .runtime.RemotePluginTestRunner.main(RemotePluginTestRunner.java:62)
>>> at
>>> org
>>> .eclipse
>>> .pde
>>> .internal
>>> .junit.runtime.CoreTestApplication.run(CoreTestApplication.java:23)
>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>> at
>>> sun
>>> .reflect
>>> .NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>> at
>>> sun
>>> .reflect
>>> .DelegatingMethodAccessorImpl
>>> .invoke(DelegatingMethodAccessorImpl.java:43)
>>> at java.lang.reflect.Method.invoke(Method.java:623)
>>> at
>>> org
>>> .eclipse
>>> .equinox
>>> .internal
>>> .app
>>> .EclipseAppContainer
>>> .callMethodWithException(EclipseAppContainer.java:574)
>>> at
>>> org
>>> .eclipse
>>> .equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:
>>> 196)
>>> at
>>> org
>>> .eclipse
>>> .core
>>> .runtime
>>> .internal
>>> .adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:
>>> 110)
>>> at
>>> org
>>> .eclipse
>>> .core
>>> .runtime
>>> .internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:
>>> 79)
>>> at
>>> org
>>> .eclipse
>>> .core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368)
>>> at
>>> org
>>> .eclipse
>>> .core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>> at
>>> sun
>>> .reflect
>>> .NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>>> at
>>> sun
>>> .reflect
>>> .DelegatingMethodAccessorImpl
>>> .invoke(DelegatingMethodAccessorImpl.java:43)
>>> at java.lang.reflect.Method.invoke(Method.java:623)
>>> at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559)
>>> at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
>>> at org.eclipse.equinox.launcher.Main.run(Main.java:1311)
>>> at org.eclipse.equinox.launcher.Main.main(Main.java:1287)
>>> Caused by: java.lang.ClassNotFoundException: InstanceTest.7572081
>>> at
>>> org
>>> .eclipse
>>> .osgi
>>> .internal.loader.BundleLoader.findClassInternal(BundleLoader.java:
>>> 494)
>>> at
>>> org
>>> .eclipse
>>> .osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
>>> at
>>> org
>>> .eclipse
>>> .osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:398)
>>> at
>>> org
>>> .eclipse
>>> .osgi
>>> .internal
>>> .baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:
>>> 105)
>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:331)
>>> ... 41 more
>>>
>>>
>>>
>>> _______________________________________________
>>> mlvm-dev mailing list
>>> mlvm-dev at openjdk.java.net
>>> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>>
>>
>>
>> _______________________________________________
>> mlvm-dev mailing list
>> mlvm-dev at openjdk.java.net
>> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>
>
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20090810/1cc52ab9/attachment.html
More information about the mlvm-dev
mailing list