Can't instantiate anonymous class more than 16 times
Wei Yin Teo
weiyinteo at gmail.com
Tue Aug 11 14:14:25 PDT 2009
I tried both: true and false. :)
In fact, setting it to true would fail the first time. In
ReflectionFactory.newConstructorAccessor, we have
if (noInflation) {
return new MethodAccessorGenerator().
generateConstructor(c.getDeclaringClass(),
c.getParameterTypes(),
c.getExceptionTypes(),
c.getModifiers());
} else {
NativeConstructorAccessorImpl acc =
new NativeConstructorAccessorImpl(c);
DelegatingConstructorAccessorImpl res =
new DelegatingConstructorAccessorImpl(acc);
acc.setParent(res);
return res;
}
We get the generated bytecode constructor the first time instead when
the threshold is exceeded.
On 11 Aug 2009, at 21:47, Rémi Forax wrote:
> Le 11/08/2009 21:03, Wei Yin Teo a écrit :
>>
>>
>>
>> On 11 Aug 2009, at 02:09, Rémi Forax wrote:
>>
>>> Le 11/08/2009 00:49, Wei Yin Teo a écrit :
>>>>
>>>> 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.
>>>
>>> You're right the problem is in package sun.reflect but the problem
>>> is not
>>> a dot transformed to a slash or vice-versa.
>>>
>>> Class.forName() uses class loader mechanism, and anonymous class
>>> aren't registered
>>> in any classloader cache. The reflection factory (here
>>> MethodAccessorGenerator)
>>> generates a bytecode with the name of the anonymous class in the
>>> constant pool
>>> to be able to call the constructor of the anonymous class.
>>> When this bytecode is loaded, the VM tries to resolve it with a
>>> classloader mechanism,
>>> so it fails throwing a NoClassDefFound.
>>>
>>> So, short time workaround:
>>> use -Dsun.reflect.noInflation=false
>>
>> Apparently, this doesn't work as you can see the above
>> newInstance(..) calls
>> MethodAccessorGenerator().generateConstructor(...) when the
>> threshold is exceeded. Shouldn't it call
>> ReflectionFactory.newConstructorAccessor(), which is guarded by the
>> system property, instead?
>
> oup, sorry
> -Dsun.reflect.noInflation=true
>
> Rémi
> _______________________________________________
> 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/20090811/ae733a31/attachment.html
More information about the mlvm-dev
mailing list