-
Bug
-
Resolution: Duplicate
-
P2
-
None
-
OpenJDK build of jdk8/tl repository.
-
b81
For some virtual method handles, MethodHandleInfo reports their reference kind incorrectly. The following program (runnable TestNG test case) produces a classfile which does an LDC on "invokevirtual String.toUpperCase", but it is reported as being an invokespecial MH instead.
@Test
public class GenBadMHTest {
public void testMHForStringToUpper() throws IOException, ReflectiveOperationException {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
cw.visit(51, ACC_SUPER + ACC_PUBLIC, "Foo", null, "java/lang/Object", new String[0]);
// Constructor
MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
ctor.visitCode();
ctor.visitVarInsn(ALOAD, 0);
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
ctor.visitInsn(RETURN);
ctor.visitMaxs(-1, -1);
ctor.visitEnd();
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "foo", "()Ljava/lang/Object;", null, null);
mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEVIRTUAL, "java/lang/String", "toUpperCase", "()Ljava/lang/String;"));
mv.visitInsn(ARETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
cw.visitEnd();
byte[] bytes = cw.toByteArray();
File f = new File("Foo.class");
try (FileOutputStream fos = new FileOutputStream(f)) {
fos.write(bytes);
}
List<URL> list = new ArrayList<>();
System.out.println(f.getCanonicalFile().getParent());
list.add(new URL("file:" + f.getCanonicalFile().getParent().toString().replace("\\", "/") + "/"));
Class clazz = Class.forName("Foo", true, new URLClassLoader(list.toArray(new URL[list.size()])));
Method m = clazz.getMethod("foo");
MethodHandle mh = (MethodHandle) m.invoke(clazz.newInstance());
MethodHandleInfo mhi = new MethodHandleInfo(mh);
assertTrue(mhi.getReferenceKind() == MethodHandleInfo.REF_invokeVirtual);
}
}
Javap listing of generated class:
brian:test-ng$ javap -c -v Foo
Classfile /home/brian/work/lambda/lambda/jdk/test-ng/Foo.class
Last modified Dec 17, 2012; size 249 bytes
MD5 checksum bec790a14e97276bf262412294213fea
public class Foo
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Utf8 Foo
#2 = Class #1 // Foo
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = NameAndType #5:#6 // "<init>":()V
#8 = Methodref #4.#7 // java/lang/Object."<init>":()V
#9 = Utf8 foo
#10 = Utf8 ()Ljava/lang/Object;
#11 = Utf8 java/lang/String
#12 = Class #11 // java/lang/String
#13 = Utf8 toUpperCase
#14 = Utf8 ()Ljava/lang/String;
#15 = NameAndType #13:#14 // toUpperCase:()Ljava/lang/String;
#16 = Methodref #12.#15 // java/lang/String.toUpperCase:()Ljava/lang/String;
#17 = MethodHandle #5:#16 // invokevirtual java/lang/String.toUpperCase:()Ljava/lang/String;
#18 = Utf8 Code
{
public Foo();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public java.lang.Object foo();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: ldc #17 // MethodHandle invokevirtual java/lang/String.toUpperCase:()Ljava/lang/String;
2: areturn
}
@Test
public class GenBadMHTest {
public void testMHForStringToUpper() throws IOException, ReflectiveOperationException {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
cw.visit(51, ACC_SUPER + ACC_PUBLIC, "Foo", null, "java/lang/Object", new String[0]);
// Constructor
MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
ctor.visitCode();
ctor.visitVarInsn(ALOAD, 0);
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
ctor.visitInsn(RETURN);
ctor.visitMaxs(-1, -1);
ctor.visitEnd();
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "foo", "()Ljava/lang/Object;", null, null);
mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEVIRTUAL, "java/lang/String", "toUpperCase", "()Ljava/lang/String;"));
mv.visitInsn(ARETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
cw.visitEnd();
byte[] bytes = cw.toByteArray();
File f = new File("Foo.class");
try (FileOutputStream fos = new FileOutputStream(f)) {
fos.write(bytes);
}
List<URL> list = new ArrayList<>();
System.out.println(f.getCanonicalFile().getParent());
list.add(new URL("file:" + f.getCanonicalFile().getParent().toString().replace("\\", "/") + "/"));
Class clazz = Class.forName("Foo", true, new URLClassLoader(list.toArray(new URL[list.size()])));
Method m = clazz.getMethod("foo");
MethodHandle mh = (MethodHandle) m.invoke(clazz.newInstance());
MethodHandleInfo mhi = new MethodHandleInfo(mh);
assertTrue(mhi.getReferenceKind() == MethodHandleInfo.REF_invokeVirtual);
}
}
Javap listing of generated class:
brian:test-ng$ javap -c -v Foo
Classfile /home/brian/work/lambda/lambda/jdk/test-ng/Foo.class
Last modified Dec 17, 2012; size 249 bytes
MD5 checksum bec790a14e97276bf262412294213fea
public class Foo
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Utf8 Foo
#2 = Class #1 // Foo
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = NameAndType #5:#6 // "<init>":()V
#8 = Methodref #4.#7 // java/lang/Object."<init>":()V
#9 = Utf8 foo
#10 = Utf8 ()Ljava/lang/Object;
#11 = Utf8 java/lang/String
#12 = Class #11 // java/lang/String
#13 = Utf8 toUpperCase
#14 = Utf8 ()Ljava/lang/String;
#15 = NameAndType #13:#14 // toUpperCase:()Ljava/lang/String;
#16 = Methodref #12.#15 // java/lang/String.toUpperCase:()Ljava/lang/String;
#17 = MethodHandle #5:#16 // invokevirtual java/lang/String.toUpperCase:()Ljava/lang/String;
#18 = Utf8 Code
{
public Foo();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public java.lang.Object foo();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: ldc #17 // MethodHandle invokevirtual java/lang/String.toUpperCase:()Ljava/lang/String;
2: areturn
}
- blocks
-
JDK-8010433 Remove lambda metafactory work-around to JDK-8005119
-
- Closed
-
- duplicates
-
JDK-7087570 java.lang.invoke.MemberName information wrong for method handles created with findConstructor
-
- Resolved
-