使用反射对 Streams 进行非法反射访问

Illegal reflective access on Streams using reflection

我正在使用反射来调用 java.util.stream.Stream 上的方法,但是因为实际实现(ReferencePipeline 等)有实际运行的代码,所以我在调用 method.setAccessible(true) 时收到非法反射访问警告,没有那个电话,它就不起作用。我想知道是否有一种方法可以自动将其委托给访问不非法的超级方法?也就是说,我想在 java.util.stream.Stream 合法的地方调用 filter 而不是 ReferencePipeline 或任何实现。

编辑这是一些代码。 target是通过反射获得的Stream的具体实例。

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);
}

使用接口 class Stream 而不是实现 class 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,您的 class 也无法使用反射访问这些 classes。

Stream.class.getMethods() 方法会起作用,因为您的 class 可以访问 public Stream class。请参阅 sun.reflect.Reflection.ensureMemberAccess() 检查您是否需要详细信息。