Can't instantiate anonymous class more than 16 times
Rémi Forax
forax at univ-mlv.fr
Tue Aug 11 15:05:21 PDT 2009
Le 11/08/2009 23:14, Wei Yin Teo a écrit :
> 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.
I see two other solution, you can bump the threshold to Integer.MAX_VALUE
or use this gory hack :)
Constructor<?> constructor =
testClass.getConstructor((Class<?>[])null);
constructor.newInstance(); // Initialize accessor which is lazily
created
Field constructorPrimaryAccessorField =
Constructor.class.getDeclaredField("constructorAccessor");
constructorPrimaryAccessorField.setAccessible(true);
Object constructorPrimaryAccessor =
constructorPrimaryAccessorField.get(constructor);
// traverse delegate
Field delegateField =
constructorPrimaryAccessor.getClass().getDeclaredField("delegate");
delegateField.setAccessible(true);
Object nativeAccessor = delegateField.get(constructorPrimaryAccessor);
Field counterField =
nativeAccessor.getClass().getDeclaredField("numInvocations");
counterField.setAccessible(true);
for (int i = 0; i < 100; i++) {
try {
constructor.newInstance();
// reset counter
counterField.setInt(nativeAccessor, 0);
}
catch(Throwable e) {
...
Rémi
>
>
> 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 <mailto: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/20090812/6e6f62fc/attachment.html
More information about the mlvm-dev
mailing list