Running this with:
$ java -XX:+TraceClassLoading Main
$ java -XX:+TraceClassLoading -Dmethodref=true Main
shows that there is a difference between using a method reference and a method reflection when calling a method.
In the case of method reflection,
getDeclaredMethod(name) is called, which calls
getDeclaredMethods() and post-filters
them to find the one with the desired name. This has the side-effect of loading an argument type for a completely unrelated
method in the same class; in this case,
Target::unsued(Unused) which is not called anywhere in this program.
The fact that we're trying to look up
Target.class.getDeclaredMethod("reflect") is enough to have a side-effect of
loading the bytes for the Unused argument type, even if no class initializers actually occur. As a result, using reflection
to call methods can trigger disk I/O and (potentially) large amounts of unneed code into an application. Although not shown
Unused had super types (or super-interfaces) then these too would be recursively loaded.