Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6263317

JVMTI Spec: Need the ability to instrument native methods

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P3 P3
    • 6
    • 6
    • hotspot
    • None
    • b37
    • generic
    • generic

      With JVM TI and java.lang.instrument we now have rich
      support for instrumenting Java programming language
      methods. But what about native methods?

      The NativeMethodBind event allows us to interpose a native
      function around the implementation of a native method. This
      works well for known native methods which we want to
      intercept -- since we can hand craft the interposer.
      However, for arbitrary native methods it would require
      generating native code on the fly that could do arbitrary
      argument processing. This would be an implementation and
      testing nightmare, and worse it is platform specific.

      We need an approach which avoids the above. Interposing
      at the Java programming language level would achieve this.
      It also has the advantage that it is at the same level as
      Java programming language method instrumentation.

      For example, if we had:

        native boolean foo(int x);

      We could transform the class file (at load time, since
      this transformation isn't allowed in a redefine) so that
      this becomes:

        boolean foo(int x) {
           ... record entry to foo ...
           return wrapper_foo(x);
        }

        native boolean wrapped_foo(int x);

      Where foo becomes a wrapper for the actual native method
      with the appended prefix "wrapped_". Note that
      "wrapped_" would be a bad prefix and that something like
      "$$$MyAgentWrapped$$$_" would be better but would make
      these examples less readable.

      But now the problem is linking up the wrapped method with
      the native implementation. That is, the method
      wrapped_foo needs to be resolved to the native
      implementation of foo, e.g.:

        Java_somePackage_someClass_foo(JNIEnv* env, jint x)

      There are two ways that resolution occurs, explicit
      resolution with the JNI function RegisterNatives and
      the normal automatic resolution. For RegisterNatives, it
      will attempt this association:

        method(foo) -> nativeImplementation(foo)

      This needs to be changed to:

        method(wrapped_foo) -> nativeImplementation(foo)

      For automatic resolution, it will attempt:

        method(wrapped_foo) -> nativeImplementation(wrapped_foo)

      This needs to be changed to:

        method(wrapped_foo) -> nativeImplementation(foo)

      Possible solutions:

      (1) Build some prefix into the VM to try on failure.

        Besides being a hack, this won't work if there are
        multiple agents wrapping native methods.

      (2) For RegisterNatives the JNI interception functionality
         could be used to change the arguments.

        Yes, but there are order of wrapper application issues
        for multiple agents.

      (3) Provide events on native resolution failure.

        This will work. But to work in a multiple agent case
        the events would be complex and very specifically tied
        to this application. For example: the event on
        automatic resolution failure would have to be called
        in the reverse environment ordering from standard event
        processing in order the remove the last prefix first,
        both events would need to have before and after strings,
        and each agent getting the RegisterNatives case would
        have to check intermediate links in the wrapper chain.

      (4) Each environment can specify a native method prefix.

        This is what I propose. It is simple and easy to use.
        It is uncomfortably specific to this application, but
        per the event solution above, this is unavoidable.

      The JVM TI function could simply be:

        jvmtiError SetNativeMethodPrefix(jvmtiEnv* env,
                                         char* prefix);

      What about java.lang.instrument, it would have the analog:

        void setNativeMethodPrefix(ClassFileTransformer transformer,
                                   String prefix);

      But the JVM TI agent that implements java.lang.instrument
      (at least in the RI) is a meta agent, that is, there is
      one JVM TI environment no matter how many
      java.lang.instrument agents there are. So, the JVM TI
      function will need to be:

        jvmtiError SetNativeMethodPrefixes(jvmtiEnv* env,
                                           jint prefixCount,
                                           char** prefixes);

      ###@###.### 2005-04-29 01:13:37 GMT

            rfield Robert Field (Inactive)
            rfield Robert Field (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: