0

Recently I am reading the JDK 19(the JDK 8,11,12 the reflection code seems did not change, so any version is ok) source code about reflection. The key to get class like this in reflection.cpp C++ class Reflection::invoke_method method:

  oop mirror             = java_lang_reflect_Method::clazz(method_mirror);

get the class instance like this:

InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(mirror));

I found the native code invoke the java class by using JNI to get the class. why using native code to implement the reflection? what is the advantage of native code to implement reflection? I am googled and found no one talk about this.

PS: I have also read the reflection could implement by Java with bytecode.

Dolphin
  • 29,069
  • 61
  • 260
  • 539
spark
  • 663
  • 1
  • 5
  • 18
  • Well ... you can't express the semantics of reflection in regular Java, so it stands to reason that it must be done with some under-the-hood native code "magic" in the JVM itself. – Stephen C Apr 05 '22 at 05:30
  • 1
    "What is the advantage of native code to implement reflection?" - The "advantage" is that it works :-) – Stephen C Apr 05 '22 at 05:33
  • how about using the bytecode to implement the reflection directly?@StephenC – Dolphin Apr 05 '22 at 05:41
  • 1
    @Dolphin are you sure the OP read about bytecode *as **you** added to question*? very strange, not to say controversial, having your question added – user16320675 Apr 05 '22 at 05:46
  • What bytecodes? There are no bytecodes that do reflection. – Stephen C Apr 05 '22 at 05:48
  • OK ... so we are now in "what if" territory. Suffice it to say that the smart people who designed this stuff ... back in the 1990's ... would have looked at all of these ideas. What they have come up with is a language + JVM design that allows non-reflective code to be compiled to native code by the JIT compiler. If they did reflection differently (e.g. by changing the Java language and/or the bytecode instruction set) they would probably need to reimplement large parts of the JVM to make it work. And my guess is that the end result would be **slower** ... – Stephen C Apr 05 '22 at 05:54
  • Now if you (or your PhD students) wanted to give it a go ... that's fine. But someone needs to demonstrate the value proposition ... before the OpenJDK team would even dream of making this kind of change in the codebase. – Stephen C Apr 05 '22 at 05:58
  • Or to put it another way, the fact (or in this case theory) that something *could* be done, doesn't mean that it *should* be done. – Stephen C Apr 05 '22 at 06:01
  • Note that you can use [JNI to invoke methods](https://docs.oracle.com/en/java/javase/18/docs/specs/jni/functions.html#calltypemethod-routines-calltypemethoda-routines-calltypemethodv-routines) - so... this has to be implemented somewhere. And early Java versions (before 1.5 iirc) did just use JNI to invoke the methods. Then dynamic bytecode generation was added. And in Java 18 reflection now uses MethodHandles under the hood. – Johannes Kuhn Apr 05 '22 at 06:18
  • 1
    @JohannesKuhn the change to not only use JNI happened around 1.3 The reimplementation to use `MethodHandle` is covered by [JDK-8266010](https://bugs.openjdk.java.net/browse/JDK-8266010). – Holger Apr 05 '22 at 09:25
  • Maybe 1.4: https://docs.oracle.com/javase/7/docs/technotes/guides/reflection/enhancements.html - although it's hard to tell from that short note. – Johannes Kuhn Apr 05 '22 at 09:44
  • 2
    @JohannesKuhn as far as I could find out, there were changes made in 1.3, which had negative impact in some scenarios, so it was reworked again in 1.4, which resulted in the implementation that lasted until JDK 18. – Holger Apr 05 '22 at 10:20
  • 2
    @user16320675 seems, “spark” mixed up the accounts. – Holger Apr 05 '22 at 11:15

1 Answers1

0

Actually the JVM team have already tell you the answer, from the comment in ReflectionFactory.java, the comment like this:

    //
    // "Inflation" mechanism. Loading bytecodes to implement
    // Method.invoke() and Constructor.newInstance() currently costs
    // 3-4x more than an invocation via native code for the first
    // invocation (though subsequent invocations have been benchmarked
    // to be over 20x faster). Unfortunately this cost increases
    // startup time for certain applications that use reflection
    // intensively (but only once per class) to bootstrap themselves.
    // To avoid this penalty we reuse the existing JVM entry points
    // for the first few invocations of Methods and Constructors and
    // then switch to the bytecode-based implementations.
    //
    // Package-private to be accessible to NativeMethodAccessorImpl
    // and NativeConstructorAccessorImpl

that's why we need native reflection.

Dolphin
  • 29,069
  • 61
  • 260
  • 539