Reputation: 51
Java doc of MethodHandle says that private method should invoke via findSpecial.But in the following example I am able to invoke it via findVirtual.
Could somebody please explain what am I missing here?
import java.lang.invoke.MethodHandles;
import java.lang.invoke.*;
import java.lang.invoke.MethodType;
public class PrivateClassMethodLookupTest{
public static void main(String[] args) throws Throwable{
new PrivateClassMethodLookupTest().m();
MethodHandle mh = MethodHandles.lookup()
.findVirtual(PrivateClassMethodLookupTest.class, "m", MethodType.methodType(void.class));
mh.invoke(new PrivateClassMethodLookupTest());
}
private void m() { System.out.println("in m");}
}
Upvotes: 5
Views: 2795
Reputation: 3003
You able to invoke it because you have access to private methods from the same class, where main
is running
Try run this code:
package com.company;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class PrivateClassMethodLookupTest {
public static void main(String[] args) throws Throwable {
new PrivateClassMethodLookupTest.Inner().m();
MethodHandle mh = MethodHandles.lookup()
.findVirtual(PrivateClassMethodLookupTest.Inner.class, "m", MethodType.methodType(void.class));
mh.invoke(new PrivateClassMethodLookupTest.Inner());
}
static class Inner {
private void m() {
System.out.println("in m");
}
}
}
To call private methods you should use Reflection API and change method access type:
package com.company;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
public class PrivateClassMethodLookupTest {
public static void main(String[] args) throws Throwable {
new PrivateClassMethodLookupTest.Inner().m();
Method declaredMethod = PrivateClassMethodLookupTest.Inner.class.getDeclaredMethod("m");
declaredMethod.setAccessible(true);
MethodHandle mh = MethodHandles.lookup().unreflect(declaredMethod);
mh.invoke(new PrivateClassMethodLookupTest.Inner());
}
static class Inner {
private void m() {
System.out.println("in m");
}
}
}
Update for Java 11 +
Code with error
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class PrivateClassMethodLookupTest {
public static void main(String[] args) throws Throwable {
new Inner().m();
MethodHandle mh = MethodHandles.lookup()
.findVirtual(Inner.class, "m", MethodType.methodType(void.class));
mh.invoke(new Inner());
}
}
class Inner {
private void m() {
System.out.println("in m");
}
}
Working version with reflection API
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Throwable {
new Inner().m();
Method declaredMethod = Inner.class.getDeclaredMethod("m");
declaredMethod.setAccessible(true);
MethodHandle mh =
MethodHandles.lookup().unreflect(declaredMethod);
mh.invoke(new Inner());
}
}
class Inner {
private void m() {
System.out.println("in m");
}
}
Upvotes: 3