The runtime of jdk7 b58 doesn't work too. java -cp test-classes/ fr.umlv.indy.visitor.test.Main0 Java HotSpot(TM) Server VM warning: JSR 292 method handles are disabled in this JVM. Use -XX:+EnableMethodHandles to enable. Exception in thread "main" java.lang.UnsatisfiedLinkError: sun.dyn.MethodHandleNatives.getConstant(I)I at sun.dyn.MethodHandleNatives.getConstant(Native Method) at sun.dyn.MethodHandleNatives.<clinit>(MethodHandleNatives.java:133) at sun.dyn.MemberName.<init>(MemberName.java:291) at java.dyn.MethodHandles$Lookup.unreflect(MethodHandles.java:307) at fr.umlv.indy.visitor.AbstractVisitor.<init>(AbstractVisitor.java:41) at fr.umlv.indy.visitor.test.Main0$1.<init>(Main0.java:7) at fr.umlv.indy.visitor.test.Main0.main(Main0.java:7)
Here, the behavior is Ok, I need to enable method handles. java -cp test-classes/ -XX:+EnableMethodHandles fr.umlv.indy.visitor.test.Main0 Java HotSpot(TM) Server VM warning: JSR 292 invokedynamic is disabled in this JVM. Use -XX:+EnableInvokeDynamic to enable. Exception in thread "main" java.lang.NoClassDefFoundError: fr/umlv/indy/visitor/AbstractVisitor at fr.umlv.indy.visitor.AbstractVisitor.genericVisit(AbstractVisitor.java:73) at fr.umlv.indy.visitor.test.Main0.main(Main0.java:19) I love this error message, NoClassDefFound AbstractVisitor in genericVisit of AbstractVisitor ?? Ok, perhaps the message is just not the good one. Moreover, the VM asks for enabling invoke dynamic but the code (below) doesn't use it ? The line 73 of AbstractVisitor.genericVisit is an invokevistual on a MethodHandle. handle(target.getClass()).<void>invoke(this, target); It's a regression, this code was working with tl/hotspot (changeset 738:53d9bf689e80). I have checked if it is not because the compiler use invokedynamic instead of invokevirtual but this is not the case : public void genericVisit(java.lang.Object); Code: 0: aload_0 1: aload_1 2: invokevirtual #5; //Method java/lang/Object.getClass:()Ljava/lang/Class; 5: invokevirtual #40; //Method handle:(Ljava/lang/Class;)Ljava/dyn/MethodHandle; 8: aload_0 9: aload_1 10: invokevirtual #41; //Method java/dyn/MethodHandle.invoke:(Lfr/umlv/indy/visitor/AbstractVisitor;Ljava/lang/Object;)V 13: return Trying to enable invoke dynamic : java -cp test-classes/ -XX:+EnableInvokeDynamic fr.umlv.indy.visitor.test.Main0 Exception in thread "main" java.lang.NoClassDefFoundError: fr/umlv/indy/visitor/AbstractVisitor at fr.umlv.indy.visitor.AbstractVisitor.genericVisit(AbstractVisitor.java:73) at fr.umlv.indy.visitor.test.Main0.main(Main0.java:19) It doesn't work, same stupid error. It seems that something goes wrong between hotspot code in tl and its integration in jdk7 workspace. I hope this mail will help ! Rémi PS: here are the two classes I have used, if you want to reproduce the bug. ----------------------------------------------------------------------------------------------------------------- package fr.umlv.indy.visitor; import java.dyn.MethodHandle; import java.dyn.MethodHandles; import java.dyn.MethodType; import java.dyn.MethodHandles.Lookup; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; public abstract class AbstractVisitor { private final ConcurrentHashMap<Class<?>, MethodHandle> map; protected AbstractVisitor() { ConcurrentHashMap<Class<?>, MethodHandle> map= new ConcurrentHashMap<Class<?>, MethodHandle>(); // should use public lookup but NPE (bug, fixed in mlvm repository) // Lookup lookup = MethodHandles.Lookup.PUBLIC_LOOKUP; Lookup lookup = MethodHandles.lookup(); for(Method method : getClass().getMethods()) { if ("visit".equals(method.getName())) { Class<?>[] types = method.getParameterTypes(); if (types.length!=1) throw new IllegalStateException("wrong number of parameter "+method); Class<?> type=types[0]; if (type.isInterface() || type.isPrimitive() || method.getReturnType()!=void.class) throw new IllegalStateException("invalid method signature "+method); //System.out.println("register "+method); // should be not needed but generate currently a NPE method.setAccessible(true); //MethodHandle methodHandle = MethodHandles.Lookup.PUBLIC_LOOKUP.unreflect(method); MethodHandle methodHandle = lookup.unreflect(method); //System.out.println("methodHandle type "+methodHandle.type()); methodHandle = MethodHandles.convertArguments(methodHandle, MethodType.make(void.class, AbstractVisitor.class, Object.class)); //System.out.println("mh type "+methodHandle.type()); map.put(type, methodHandle); } } this.map=map; } private MethodHandle findNewMethodHandle(Class<?> type) { MethodHandle methodHandle=superHandle(type); map.put(type, methodHandle); return methodHandle; } private MethodHandle superHandle(Class<?> type) { ConcurrentHashMap<Class<?>, MethodHandle> map = this.map; for(Class<?> clazz=type.getSuperclass();clazz!=null;clazz=clazz.getSuperclass()) { MethodHandle methodHandle = map.get(clazz); if (methodHandle != null) { return methodHandle; } } throw new RuntimeException("no visit method applicable for "+type); } public void genericVisit(Object target) { handle(target.getClass()).<void>invoke(this, target); } public MethodHandle handle(Class<?> type) { MethodHandle methodHandle=map.get(type); if (methodHandle!=null) { return methodHandle; } return findNewMethodHandle(type); } public MethodHandle oneApplicable(Class<?> type) { MethodHandle oneApplicable=null; for(Entry<Class<?>, MethodHandle> entry:map.entrySet()) { if (type.isAssignableFrom(entry.getKey())) { if (oneApplicable==null) oneApplicable=entry.getValue(); else return null; } } return oneApplicable; } } ------------------------------------------------------------------------------------------------------------------- package fr.umlv.indy.visitor.test; import fr.umlv.indy.visitor.AbstractVisitor; public class Main0 { public static void main(String[] args) { AbstractVisitor visitor=new AbstractVisitor() { public void visit(String text) { System.out.println("text "+text); } public void visit(Integer integer) { System.out.println("integer "+integer); } public void visit(Object o) { System.out.println("object "+o); } }; visitor.genericVisit("toto"); visitor.genericVisit(3); visitor.genericVisit(4.0); } } _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev