Yet Another bug

Rémi Forax forax at univ-mlv.fr
Tue May 12 16:25:30 PDT 2009


Rémi Forax a écrit :
> John Rose a écrit :
>   
>> I hope b59 smells better.  I just pushed the changes I've chosen for  
>> b59 to the patch repo.
>>
>> I am working on other changes too, but I am in point-fix mode, as JDK7  
>> M3 settles down for JavaOne.
>>
>> My goal at the moment is to find workarounds for broken stuff, so as  
>> not to be making widespread changes.
>>
>> Here are some workarounds that will help:
>>
>> --- Use MethodHandles.lookup().findFoo(...) if you run into trouble  
>> with cached or public lookup-factories.
>>
>> Try to access only methods on the current class (the one calling  
>> lookup()), or else public methods in public classes.
>>
>> This avoids bugs with the access checking logic, by exercising the  
>> simplest forms of access checking.
>>   
>>     
> Or use reflection (getMethods()), set accessibility 
> (setAccessible(true)) and
> use MethodHandle.unreflect(java.lang.reflect.Method).
>
>   
>> --- In your method handle invocation sites and in invokedynamic sites,  
>> prefer method handles of built-in types.
>>
>> A symptom of when you might want to do this is "NoClassDefFound" at an  
>> invoke site, for an application class that obviously exists.
>>
>> Generally speaking, the inserted leading argument type to  
>> Lookup.findVirtual only gets in the way.  Use convertArguments to  
>> change the leading argument to Object, or bind it to an instance  
>> immediately.
>>   
>>     
> I've found that if you convert the leading argument of the method handler,
> you have to cast the leading argument of MethodHandle.invoke() too.
>
> // in my example
> methodHandle = MethodHandles.convertArguments(methodHandle,
>             MethodType.make(void.class,
>                 /*AbstractVisitor.class*/ Object.class,  // workaround 
> to NoClassDefFound bug
>                 Object.class));
>
> // and then
> methodHandle.<void>invoke((Object)this, target);
>           cast is needed here  ------^
>
>   
>> --- When currying method handles with insertArgument, insert only a  
>> leading argument (#0) to a direct method handle.
>>
>> If you have something more complicated you want to do with currying,  
>> consider using a JavaMethodHandle instead.
>>
>> (Yes, all this should be taken care of for you, and it will be!)
>>
>> -- John
>>   
>>     
>
> And it works like a charm :)
>   
untile the next bug ...
The following code crash.
It doesn't crash if there is only one invokedynamic.

public class YACrash {
  public void m(Object o) {
    System.out.println("m "+o);
  }
 
  public static void main(String[] args) {
    YACrash crash = new YACrash();
    InvokeDynamic.<void>call((Object)crash, 3);
    InvokeDynamic.<void>call((Object)crash, 4.0); // crash occurs here
  }
 
  static final MethodHandle stub;
  static {
    Linkage.registerBootstrapMethod("linker");
   
    MethodHandle mh=MethodHandles.lookup().findVirtual(YACrash.class, 
"m", MethodType.make(void.class, Object.class));
   
    mh=MethodHandles.convertArguments(
        mh,
        MethodType.make(void.class, Object.class, Object.class));
    stub=mh;
  }
 
  public static CallSite linker(Class<?> declaringClass, String name, 
MethodType type) {
    return new CallSite(declaringClass, name, type) {
      @Override
      protected MethodHandle initialTarget() {
        return MethodHandles.convertArguments(
            stub,
            type());
      }
    };
  }
}

Rémi



More information about the mlvm-dev mailing list