Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Вызов private методов через LambdaMetafactory Java 8

Instance Klass Профи (747), на голосовании 4 месяца назад
*** Проблема решена, вопрос закрыт ***
-------------
Мне нужно вызвать метод, который имеет модификатор доступа private, для этой задачи рефлексия и MethodHandle довольно медленные, ибо я это собираюсь вызывать менее чем каждые 50 миллисекунд и соответственно просадка в производительности будет видна, но я нашел решение данной проблемы - использование LambdaMetafactory.metafactory, который явно быстрее будет чем эти два способа которые я назвал выше.
Проблема заключается в том, что используя MethodHandles.lookup() мне выдаёт следующую ошибку: java.lang.IllegalAccessException: member is private: метод который я вызываю from мой класс, я пробовал использовать IMPL_LOOKUP, который получаю через ту самую рефлексию, либо же через Unsafe (в общем то не важно), но теперь у меня другая проблема, LambdaMetafactory отказывается видеть мой интерфейс, то есть в defineAnonymousClass пишет ошибку, что мой интерфейс не найден почему-то, возможно всё дело в разных загрузчиков классах, но я пытался загрузить свой интерфейс через системный загрузчик, что не помогло. Кто-то сталкивался с подобным или может как-нибудь, пожалуйста, помочь?
Голосование за лучший ответ
V̲i̲s̲t̲a̲s̲t̲e̲r̲ Искусственный Интеллект (263832) 5 месяцев назад
в Java 9 вроде этот вопрос решен. А так нужны обходные манёвры. Вот содранный вариант частичного решения кэшированием MethodHandle


 import java.lang.invoke.MethodHandle; 
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;

public class Main {
private static final MethodHandle PRIVATE_METHOD_HANDLE;

static {
try {
// Получение доступа к привилегированному Lookup
Field lookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
lookupField.setAccessible(true);
MethodHandles.Lookup lookup = (MethodHandles.Lookup) lookupField.get(null);

// Получение MethodHandle для приватного метода
PRIVATE_METHOD_HANDLE = lookup.findSpecial(
MyClass.class,
"myPrivateMethod",
MethodType.methodType(void.class),
MyClass.class
);
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}

public static void main(String[] args) throws Throwable {
// Создание экземпляра класса MyClass
MyClass myClassInstance = new MyClass();

// Вызов приватного метода через кешированный MethodHandle
PRIVATE_METHOD_HANDLE.invoke(myClassInstance);
}
}

// Класс с приватным методом
class MyClass {
private void myPrivateMethod() {
System.out.println("Private method called!");
}
}
Instance KlassПрофи (747) 5 месяцев назад
Да, и вправду он быстрее чем обычное создание и использование MethodHandle, но всё равно не настолько быстр как использование лямбд. К слову, я уже решил свой вопрос
Instance KlassПрофи (747) 5 месяцев назад
К сожалению, скорость MethodHandle такая же, как у непосредственного вызова метода - только если метод статичен
Instance Klass, а что ты ожидал от интроспекции? Эти механизмы - по определению медленные, хочешь быстрое - пиши своё, под свою задачу.
Похожие вопросы