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@openjdk.java.net <mailto:mlvm-dev@openjdk.java.net>
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
------------------------------------------------------------------------
_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev