Михаил Богданов
2016-11-14 09:58:47 UTC
JDK 8 incorrectly processes nameless (name=null) parameters in MethodParameters attribute. Actually problem in inconsistency between Hotspot and reflection:
Hotspot VM constructs nameless parameter with empty string name that cause Executable.verifyParameters to throw MalformedParametersException.
//Code to reproduce:import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class Bug {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
ClassWriter writer = new ClassWriter(Opcodes.ASM5);
writer.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, "Test", null, "java/lang/Object", null);
MethodVisitor test = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, "test", "(I)V", null, null);
test.visitParameter(null, 0);
test.visitEnd();
writer.visitEnd();
final byte[] bytes = writer.toByteArray();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], ClassLoader.getSystemClassLoader()) {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (name.equals("Test")) {
return defineClass("Test", bytes, 0, bytes.length);
}
return super.findClass(name);
}
};
Class<?> clazz = urlClassLoader.loadClass("Test");
Method method = clazz.getDeclaredMethod("test", Integer.TYPE);
// Exception in thread "main" java.lang.reflect.MalformedParametersException: Invalid parameter name ""
// at java.lang.reflect.Executable.verifyParameters(Executable.java:386)
// at java.lang.reflect.Executable.privateGetParameters(Executable.java:416)
// at java.lang.reflect.Executable.getParameters(Executable.java:357)
// at Bug.main(Bug.java:37)
method.getParameters();
}
}
Best regards, Max
Hotspot VM constructs nameless parameter with empty string name that cause Executable.verifyParameters to throw MalformedParametersException.
//Code to reproduce:import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class Bug {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
ClassWriter writer = new ClassWriter(Opcodes.ASM5);
writer.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, "Test", null, "java/lang/Object", null);
MethodVisitor test = writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, "test", "(I)V", null, null);
test.visitParameter(null, 0);
test.visitEnd();
writer.visitEnd();
final byte[] bytes = writer.toByteArray();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], ClassLoader.getSystemClassLoader()) {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (name.equals("Test")) {
return defineClass("Test", bytes, 0, bytes.length);
}
return super.findClass(name);
}
};
Class<?> clazz = urlClassLoader.loadClass("Test");
Method method = clazz.getDeclaredMethod("test", Integer.TYPE);
// Exception in thread "main" java.lang.reflect.MalformedParametersException: Invalid parameter name ""
// at java.lang.reflect.Executable.verifyParameters(Executable.java:386)
// at java.lang.reflect.Executable.privateGetParameters(Executable.java:416)
// at java.lang.reflect.Executable.getParameters(Executable.java:357)
// at Bug.main(Bug.java:37)
method.getParameters();
}
}
Best regards, Max