Нелегальный рефлексивный доступ на потоках с использованием рефлексии - PullRequest
0 голосов
/ 14 ноября 2018

Я использую рефлексию для вызова методов на java.util.stream.Stream, но поскольку фактические реализации (ReferencePipeline и т. Д.) Имеют реальный код, который запускается, я получаю недопустимые рефлексивные предупреждения о доступе при вызове method.setAccessible(true) и без этот звонок, это не работает. Мне было интересно, есть ли способ автоматически делегировать это супер-метод, где доступ не является незаконным? То есть я хочу вызвать filter там, где это разрешено java.util.stream.Stream, а не ReferencePipeline или какой-либо другой реализацией.

РЕДАКТИРОВАТЬ Вот некоторый код. target является конкретным примером потока, полученного с помощью отражения.

assert target instanceof java.util.stream.Stream;

Method candidate = Stream.of(target.getClass().getMethods())
    .filter(method -> method.getName().equals("filter"))
    //.filter(myComplicatedCriteria) - omitted for brevity
    .findAny().orElseThrow();

try {
    candidate.setAccessible(true);
    return candidate.invoke(target, candidateParameterValues);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
    throw new EolRuntimeException(ex);
}

1 Ответ

0 голосов
/ 14 ноября 2018

Используйте класс интерфейса Stream вместо реализующего класса target.getClass(). Измените код на:

Method candidate = Stream.of(Stream.class.getMethods())
        .filter(method -> method.getName().equals("filter"))
        ...  

Основная причина проблемы: java.util.stream.ReferencePipeline, а также java.util.stream.ReferencePipeline.Head, защищенная пакетом. Ваш класс не может получить доступ к этим классам, используя отражение, даже если сам метод filter() определен как public.

Подход Stream.class.getMethods() будет работать, потому что ваш класс может получить доступ к общедоступному классу Stream. Смотрите sun.reflect.Reflection.ensureMemberAccess() проверьте, если вам нужны подробности.

...