I'm using reflection to invoke methods on java.util.stream.Stream but because the actual implementations (ReferencePipeline etc.) have the actual code which runs, I get illegal reflective access warnings when calling method.setAccessible(true)
, and without that call, it doesn't work. I was wondering whether there is a way to automatically delegate this to a super method where access isn't illegal? That is, I want to call filter
where it's legal on java.util.stream.Stream
and not ReferencePipeline
or whatever the implementation is.
EDIT Here is some code. target
is a concrete instance of a Stream obtained via reflection.
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);
}
Use the interface class Stream
instead of the implementing class target.getClass()
. Change the code to:
Method candidate = Stream.of(Stream.class.getMethods())
.filter(method -> method.getName().equals("filter"))
...
Root cause of the problem is java.util.stream.ReferencePipeline
as well as java.util.stream.ReferencePipeline.Head
being package protected. Your class can't access these classes using reflection even if the filter()
method itself is defined as public
.
The Stream.class.getMethods()
approach will work because your class can access the public Stream
class. See sun.reflect.Reflection.ensureMemberAccess()
check if you need details.