On 03/05/2015 04:09 AM, Jochen Theodorou wrote:
Am 04.03.2015 23:50, schrieb Charles Oliver Nutter:
On Thu, Feb 26, 2015 at 4:27 AM, Jochen Theodorou <blackd...@gmx.org> wrote:
my biggest request: allow the call of a super constructor (like
super(foo,bar)) using MethodHandles an have it understood by the JVM like a
normal super constructor call... same for this(...)

Just so I understand...the problem is that unless you can get a Lookup
that can do the super call from Java (i.e. from within a subclass),
you can't get a handle that can do the super call, right? And you
can't do that because the method bodies might not be emitted into a
natural subclass of the super class?

Not fully right. Sorry for the possibly false flag with the permissions from the runtime. I am in a natural subclass. Take this pseudoexample:

public class Foo {
  public Foo(String s, Integer i){}
  public Foo(Integer s, Object o){}
}

public class Bar extends Foo {
  public Bar(def a, def b) {
     super(a,b) // call with runtime types here
  }
}

I cannot express super(a,b) using method handles, even if I did know the types at compiletime (in which case I would not need invokedynamic anyway). Sure, there is http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandles.Lookup.html#findSpecial%28java.lang.Class,%20java.lang.String,%20java.lang.invoke.MethodType,%20java.lang.Class%29 but this is for calling methods in a invokespecial like manner, <init> is excluded here as stated in the comment. The comment refers to findConsructor for calls to constructors, and indeed we have invokeSpecial calls there as well, but those are for what in Java is "new", and are different from calls to a super constructor. See also http://mail.openjdk.java.net/pipermail/mlvm-dev/2012-June/004650.html from almost 3 years ago here on the list. Remi gives here a good reason why it probably cannot be done easily... in that or an even older thread someone (I think John) was talking about security.

bye Jochen


Hi Jochen,

Here's an idea. Let Groovy compile Foo to the following Java equivalent:

public class Foo {
    public Foo(Onject p1, Object p2) {
        super();
        invokedynamic _init(p1, p2);
    }

    private void _init(String s, Integer i) {
        // the body of constructor for (String, Integer)
    }

    private void _init(Integer s, Object o) {
        // the body of constructor for (Integer, Object)
    }
}


... a set of overloaded Groovy constructors with same arity could be emmited as:

- a single constructor with Object typed arguments chaining to a super constructor with Object typed arguments using plain invokespecial - one private void _init method with declared types of arguments per Groovy constructor containing code of related Groovy constructor - an invokedynamic call in the single emitted constructor used for dispatching to appropriate _init method based on runtime types of arguments

Only one thing would not work as expected in this setting: final fields could not be set in _init methods as verifier doesn't allow that.

So what we might need (also for other purposes like de-serialization) is a special kind of private void instance initialization methods that are treated specially by verifier and javac. The rules for such methods could be as follows:

- they are treated like constructors regarding assignment to final instance fields - they can not be called from normal code except from constructors of the same class that calls: super constructor followed by a call to one of those special initialization methods. For example:

public class Bar extends Foo {

    private final int val;

    public Bar(String s, int val) {
        super(s);
// call to special @init method can only appear immediately after call to super constructor (verifier checked) initVal(val); // ...together they have the effect of calling any this(...) constructor

        // ...so this is not allowed by javac
        this.val = 42;
    }

    @init private void initVal(int val) {
        this.val = val; // allowed and required (like in constructor)
    }

    public void normalMethod() {
        initVal(42); // not allowed by javac or verifier
    }
...


Those special @init methods could be invoked using reflection with overridden access checks (setAccessible(true)) and looked up as method handles using privileged Lookup only.


Regards, Peter

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to