8 Replies Latest reply on Apr 1, 2009 12:30 PM by jason.greene

    Multiple ClassFileTransformers/Translators

    alesj

      WRT: https://jira.jboss.org/jira/browse/JBSPRING-1
      I've created custom JBoss5 LTW: http://anonsvn.jboss.org/repos/jbossas/projects/spring-int/trunk/weaving/src/main/java/org/jboss/instrument/classloading/JBoss5ClassLoader.java

      But my actual question is really:
      * why do we use custom Translator instead of ClassFileTransformer
      ** perhaps the usage of Translator::unregisterClassLoader
      * why do we have just one translator and not a list of them
      * why Translator per ClassLoaderSystem and not (also) per BaseClassLoaderPolicy

      Afaics the SpringLTW example will set the transformer to the whole ClassLoaderSystem,
      where it would actually only make sense to have it on apps CL policy.

        • 1. Re: Multiple ClassFileTransformers/Translators

           

          "alesj" wrote:
          WRT: https://jira.jboss.org/jira/browse/JBSPRING-1


          "It does not work" is not a bug report. What's wrong with it?

          If you want to send me private e-mails asking me to look at stuff,
          at least give me something to look at. :-)

          Either way, I'll usually just ignore this kind of "twaddle" until the author puts some work into the question to make it answerable.


          I've created custom JBoss5 LTW: http://anonsvn.jboss.org/repos/jbossas/projects/spring-int/trunk/weaving/src/main/java/org/jboss/instrument/classloading/JBoss5ClassLoader.java

          But my actual question is really:
          * why do we use custom Translator instead of ClassFileTransformer
          ** perhaps the usage of Translator::unregisterClassLoader


          You should use an agent.

          The Transformer is only there for backwards compatibility with AOP from before the agent api was available.

          Something that is almost certainly no longer relevant except for some old tests in the testsuite.

          The only difference between the Transformer and the ClassFileTransformer
          is that one is inside ClassLoader.defineClass() - i.e. all classloaders
          while the other is only invoked from our ClassLoader.

          
           // Load the bytecode
           byte[] byteCode = ClassLoaderUtils.loadByteCode(name, is);
          
           // Let the policy do things before we define the class
           BaseClassLoaderPolicy basePolicy = policy;
           ProtectionDomain protectionDomain = basePolicy.getProtectionDomain(name, resourcePath);
           try
           {
          
          TRANSFORMER HERE
          
           byte[] transformed = policy.transform(name, byteCode, protectionDomain);
           if (transformed != null)
           byteCode = transformed;
           }
           catch (Throwable t)
           {
           throw new RuntimeException("Unexpected error transforming class " + name, t);
           }
          
           // Create the package if necessary
           URL codeSourceURL = null;
           if (protectionDomain != null)
           {
           CodeSource codeSource = protectionDomain.getCodeSource();
           if (codeSource != null)
           codeSourceURL = codeSource.getLocation();
           }
           definePackage(name, codeSourceURL);
          
           // Finally we can define the class
           Class<?> result;
          
          AGENT INSTRUMENTATION HERE
          
           if (protectionDomain != null)
           result = defineClass(name, byteCode, 0, byteCode.length, protectionDomain);
           else
           result = defineClass(name, byteCode, 0, byteCode.length);
          



          * why do we have just one translator and not a list of them
          * why Translator per ClassLoaderSystem and not (also) per BaseClassLoaderPolicy

          Afaics the SpringLTW example will set the transformer to the whole ClassLoaderSystem,
          where it would actually only make sense to have it on apps CL policy.


          If you want to add classloader specific ClassFileTransformers to the
          BaseClassLoaderPolicy api that's ok with me.

          I think a better integration point would be to have a Spring aop deployer like
          our aop deployer to analyse (and in your case modify) the classloader
          based on metadata?

          • 2. Re: Multiple ClassFileTransformers/Translators
            jason.greene

             

            "adrian@jboss.org" wrote:

            You should use an agent.

            The Transformer is only there for backwards compatibility with AOP from before the agent api was available.


            The problem with agents is that they scan every class, regardless of where it came from, which usually has a performance impact (although, in fairness we can probably optimize this away to an instanceof) . We also do not install one by default, and have different ones depending on the JVM (although JRockit support is going away). Since we control classloading, it seems like adding a transformer to specific domains is a better approach.




            • 3. Re: Multiple ClassFileTransformers/Translators
              alesj

               

              "adrian@jboss.org" wrote:
              "alesj" wrote:
              WRT: https://jira.jboss.org/jira/browse/JBSPRING-1


              "It does not work" is not a bug report. What's wrong with it?

              If you want to send me private e-mails asking me to look at stuff,
              at least give me something to look at. :-)

              Either way, I'll usually just ignore this kind of "twaddle" until the author puts some work into the question to make it answerable.

              My WRT wasn't really meant for you to go and do detailed analysis. :-)
              I thought the "my actual question is really" made this clear.

              The private email was about the CL 2.0.4.GA release,
              which Jason did, but didn't update the JIRA.
              Since you control that space, I thought I asked there (in private email)
              as I don't really see that as a dev question. ;-)
              The p.s. was just semi-informal. :-)

              "adrian@jboss.org" wrote:

              You should use an agent.

              The Transformer is only there for backwards compatibility with AOP from before the agent api was available.

              Something that is almost certainly no longer relevant except for some old tests in the testsuite.

              The only difference between the Transformer and the ClassFileTransformer
              is that one is inside ClassLoader.defineClass() - i.e. all classloaders
              while the other is only invoked from our ClassLoader.

              Agent is what we currently use with that Spring's LWT.
              But like Jason says, we control the classloading,
              and Spring lets you set per app per environment LWT.
              They have this for all other app servers, hence I created ours,
              which I hope will eventually 'live' in their code.

              "adrian@jboss.org" wrote:

              If you want to add classloader specific ClassFileTransformers to the
              BaseClassLoaderPolicy api that's ok with me.

              Already done.
              But I'm still using our Translator + adding ClassFileTransformer2Translator bridge.

              "adrian@jboss.org" wrote:

              I think a better integration point would be to have a Spring aop deployer like
              our aop deployer to analyse (and in your case modify) the classloader
              based on metadata?

              Could be done, but I don't see what this brings over their per app server approach.

              • 4. Re: Multiple ClassFileTransformers/Translators

                 

                "alesj" wrote:

                The private email was about the CL 2.0.4.GA release,
                which Jason did, but didn't update the JIRA.
                Since you control that space, I thought I asked there (in private email)
                as I don't really see that as a dev question. ;-)


                I don't see why the release of an open source project isn't an issue for its forum?

                I've fixed Jason's "half a job". :-) The release date was 10th March according to
                repository.jboss.com. There's now a 2.0.5.GA in JIRA.

                • 5. Re: Multiple ClassFileTransformers/Translators

                   

                  "alesj" wrote:

                  "adrian@jboss.org" wrote:

                  I think a better integration point would be to have a Spring aop deployer like
                  our aop deployer to analyse (and in your case modify) the classloader
                  based on metadata?

                  Could be done, but I don't see what this brings over their per app server approach.


                  Because if I understand what this doing (almost certainly a bad assumption :-)
                  Then its only going work properly simple cases like in web-apps or scoped ears.

                  In other environments where applications share a classloading space,
                  e.g. import-all=true or osgi style imports
                  the aop config needs to be shared/merged, otherwise point cut expressions won't get applied
                  to caller classes in other applications.

                  • 6. Re: Multiple ClassFileTransformers/Translators
                    alesj

                     

                    "alesj" wrote:

                    "adrian@jboss.org" wrote:

                    If you want to add classloader specific ClassFileTransformers to the
                    BaseClassLoaderPolicy api that's ok with me.

                    Already done.
                    But I'm still using our Translator + adding ClassFileTransformer2Translator bridge.

                    What should be the order of transformation?
                    1) domain
                    2) policy
                    Having more "exact" transformation after more "general".

                     protected byte[] transform(String className, byte[] byteCode, ProtectionDomain protectionDomain) throws Exception
                     {
                     byte[] result = byteCode;
                    
                     BaseClassLoaderDomain domain = getClassLoaderDomain();
                     if (domain != null)
                     result = domain.transform(getClassLoader(), className, result, protectionDomain);
                    
                     ClassLoader classLoader = getClassLoaderUnchecked();
                     if (classLoader != null)
                     result = TranslatorUtils.applyTranslatorsOnTransform(translators, classLoader, className, result, protectionDomain);
                    
                     return result;
                     }
                    





                    • 7. Re: Multiple ClassFileTransformers/Translators

                       

                      "alesj" wrote:

                      What should be the order of transformation?
                      1) domain
                      2) policy
                      Having more "exact" transformation after more "general".


                      I would say all of them. And if the order matters, then there's something wrong. ;-)
                      That's certainly the rule for Agents.

                      • 8. Re: Multiple ClassFileTransformers/Translators
                        jason.greene

                         

                        "adrian@jboss.org" wrote:

                        I've fixed Jason's "half a job". :-) The release date was 10th March according to
                        repository.jboss.com. There's now a 2.0.5.GA in JIRA.


                        Sorry about that, this was a late night rush job because it was blocking an AS release which was past due.