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