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

Java agents doing instrumentation need a means to define auxiliary classes

    Details

    • Type: CSR
    • Status: Draft
    • Priority: P3
    • Resolution: Unresolved
    • Fix Version/s: tbd
    • Component/s: core-svc
    • Labels:
    • Subcomponent:
    • Compatibility Risk:
      minimal
    • Compatibility Risk Description:
      New API.
    • Interface Kind:
      Java API

      Description

      Summary

      Update the java.lang.instrument API to allow agents doing load time or dynamic instrumentation to define additional classes in the same runtime package as the class being transformed.

      Problem

      Tool agents that instrument code with references to agent provided classes need to ensure that those classes are visible to the and accessible to the instrumented class. Instrumentation::appendToBootstrapClassLoaderSearch​ and appendToSystemClassLoaderSearch​ APIs are too limited - they aren't useful when the bytecode of the supporting classes is generated with the intention of being loaded into the same runtime package as the instrumented class (a non-public helper class for example).

      Solution

      Define a new java.lang.instrument.ClassFileTransformer.ClassDefiner interface and a new java.lang.instrument.ClassFileTransformer::transform method that takes ClassDefiner parameter. This way an agent can define additional classes in the same runtime package as the class being transformed.

      Specification

      • New java.lang.instrument.ClassFileTransformer.ClassDefiner interface and new java.lang.instrument.ClassFileTransformer::transform method that takes an additional ClassDefiner parameter:
          /**
           * A {@code ClassDefiner} provides the mechanism for {@code ClassFileTransformer}
           * to define additional classes during the
           * {@linkplain ClassFileTransformer#transform(ClassDefiner, Module, ClassLoader, String, Class, ProtectionDomain, byte[])
           * transformation process} of a class.
           *
           * <p> When a {@linkplain ClassFileTransformer#transform(ClassDefiner, Module, ClassLoader, String, Class, ProtectionDomain, byte[])
           * transformer} is called to retransform a class, the transformer can call
           * {@link ClassDefiner#defineClass(byte[])} to define additional classes.
           * If it is called after {@link ClassFileTransformer#transform(ClassDefiner, Module, ClassLoader, String, Class, ProtectionDomain, byte[])
           * ClassFileTransformer.tranform} method returns or called by another
           * thread, {@code IllegalStateException} will be thrown.
           *
           * @since 11
           */
          static interface ClassDefiner {
              /**
               * Defines a class of the given bytes to the runtime.
               * The given bytes will be defined to the same class loader and in the
               * same runtime package and
               * {@linkplain java.security.ProtectionDomain protection domain} as
               * the class being transformed.
               *
               * <p> No transformation is applied to the bytes passed to this
               * {@code ClassDefiner.defineClass} method.
               * {@link Instrumentation#retransformClasses(Class[])} can be called
               * later to retransform the {@code Class} returned by this method
               * if desired.
               *
               * @param bytes the class bytes
               * @return the {@code Class} object for the class
               *
               * @throws NullPointerException
               *         {@code bytes} is {@code null}
               * @throws IllegalArgumentException
               *         the bytes are for a class of a different package than
               *         the class being transformed
               * @throws LinkageError if the class is malformed ({@code ClassFormatError}),
               *         cannot be verified ({@code VerifyError}), is already defined,
               *         or another linkage error occurs
               * @throws IllegalStateException if this {@code ClassDefiner} is called
               *         by a thread other than the thread doing the transformation,
               *         or after all transformers are called.
               */
              Class<?> defineClass(byte[] bytes);
      } /**
      • Transforms the given class file and returns a new replacement class file.
        *
      • <p> A {@code ClassFileTransformer} may define additional classes
      • to the same class loader and the same runtime package as the class being
      • transformed by calling {@link ClassDefiner#defineClass(byte[]
      ) * classDefiner.defineClass} method. If an attempt to use {@code classDefiner} * is made after this {@code transform} method returns, * {@code IllegalStateException} will be thrown. * * @implSpec The default implementation of this method invokes the * {@link #transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[]) transform} * method. * * @param classDefiner a {@code ClassDefiner} that this class transformer * can define additional classes * @param module the module of the class to be transformed * @param loader the defining loader of the class to be transformed, * may be {@code null} if the bootstrap loader * @param className the name of the class in the internal form of fully * qualified class and interface names as defined in * <i>The Java Virtual Machine Specification</i>. * For example, <code>"java/util/List"</code>. * @param classBeingRedefined if this is triggered by a redefine or retransform, * the class being redefined or retransformed; * if this is a class load, {@code null} * @param protectionDomain the protection domain of the class being defined or redefined * @param classfileBuffer the input byte buffer in class file format - must not be modified * * @throws IllegalClassFormatException * if the input does not represent a well-formed class file * @return a well-formed class file buffer (the result of the transform), * or {@code null} if no transform is performed * * @since 11 */ default byte[] transform( ClassFileTransformer.ClassDefiner classDefiner, Module module, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
      • The class specification of ClassFileTransformer is updated to mention ClassDefiner.
      @@ -140,20 +138,26 @@
        * retransformed or redefined, the
        * transformer must insure that the second class output class file is a legal
        * redefinition of the first output class file.
        *
        * <P>
      + * Transformers may define additional classes when a class is
      + * being transformed via {@link ClassDefiner#defineClass(byte[])
      + * ClassDefiner.defineClass}. They will be defined to the same class loader and
      + * the same protection domain as the class being transformed.
      + *

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                mchung Mandy Chung
                Reporter:
                mchung Mandy Chung
              • Votes:
                1 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated: