1 2 Previous Next 16 Replies Latest reply on Apr 2, 2013 9:19 AM by Ales Justin

    Custom ClassLoader

    Irfan Basha Newbie

      Hi All,

       

      I am trying to create a custom classloader which I can use to load few classes in my war (may be complete war in future).

       

      I found this article which explains how a custom classloader can be created:

      (Custom ClassLoader (classloader-beans.xml)) http://java.dzone.com/articles/a-look-inside-jboss-microconta-0

       

      I have few clarifications in this:

      1) Where should I put the content of classloader-beans.xml ? (I have currently put it in jboss-beans.xml and placed it in WEB-INF)

      2) Correct me if am wrong: The bean CB2 will be loaded using the customClassLoader... right ?

       

      This is how my jboss-beans.xml looks like:

      <deployment xmlns="urn:jboss:bean-deployer:2.0">

                <classloader>

                          <inject bean="custom-classloader:0.0.0" />

                </classloader>

       

                <classloader name="custom-classloader" xmlns="urn:jboss:classloader:1.0"

                          export-all="NON_EMPTY" import-all="true" />

                <bean name="CustomCL" class="com.beans.CustomClassLoader">

                          <constructor>

                                    <parameter>

                                              <inject bean="custom-classloader:0.0.0" />

                                    </parameter>

                          </constructor>

       

                </bean>

                <bean name="CB1" class="com.Sample">

                <classloader>

                          <inject bean="CustomCL" />

                </classloader>

      </bean>

      </deployment>

       

      And I have the class CustomeClassLoader which just extends ClassLoader:

       

      public class CustomClassLoader extends ClassLoader

      {

         private Pattern pattern;

         public CustomClassLoader(ClassLoader parent)

         {

            super(parent);

         }

         public Class<?> loadClass(String name) throws ClassNotFoundException

         {

            if (pattern == null || pattern.matcher(name).matches())

               return super.loadClass(name);

            else

               throw new ClassNotFoundException("Name '" + name + "' doesn't match pattern: " + pattern);

         }

         public void setPattern(String regexp)

         {

            pattern = Pattern.compile(regexp);

         }

      }

       

      and when I start JBoss I get this following error:

      08:28:51,677 ERROR [AbstractKernelController] Error installing to PreInstall: na

      me=CustomCL state=Real

      java.lang.ClassNotFoundException: com.beans.CustomClassLoader

              at java.net.URLClassLoader$1.run(Unknown Source)

              at java.net.URLClassLoader$1.run(Unknown Source)

              at java.security.AccessController.doPrivileged(Native Method)

              at java.net.URLClassLoader.findClass(Unknown Source)

              at java.lang.ClassLoader.loadClass(ClassLoader.java:428)

              at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)

              at java.lang.ClassLoader.loadClass(ClassLoader.java:360)

              at java.lang.Class.forName0(Native Method)

              at java.lang.Class.forName(Unknown Source)

              at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseCl

      assLoaderDomain.java:304)

              at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseCl

      assLoaderDomain.java:1172)

              at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(Ba

      seClassLoader.java:1264)

              at org.jboss.classloader.spi.base.BaseClassLoader.doLoadClass(BaseClassL

      oader.java:549)

              at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoa

      der.java:497)

              at java.lang.ClassLoader.loadClass(ClassLoader.java:360)

              at java.lang.Class.forName0(Native Method)

              at java.lang.Class.forName(Unknown Source)

              at org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactoryI

      mpl.resolveComplexTypeInfo(IntrospectionTypeInfoFactoryImpl.java:419)

              at org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactoryI

      mpl.getTypeInfo(IntrospectionTypeInfoFactoryImpl.java:388)

              at org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactory.

      getTypeInfo(IntrospectionTypeInfoFactory.java:54)

              at org.jboss.classadapter.plugins.BasicClassAdapterFactory.getClassAdapt

      er(BasicClassAdapterFactory.java:61)

              at org.jboss.config.plugins.AbstractConfiguration.getBeanInfo(AbstractCo

      nfiguration.java:86)

              at org.jboss.kernel.plugins.config.AbstractKernelConfig.getBeanInfo(Abst

      ractKernelConfig.java:80)

              at org.jboss.kernel.plugins.config.AbstractKernelConfigurator.getBeanInf

      o(AbstractKernelConfigurator.java:77)

              at org.jboss.kernel.plugins.config.AbstractKernelConfigurator.getBeanInf

      o(AbstractKernelConfigurator.java:96)

              at org.jboss.kernel.plugins.dependency.PreInstallAction.installActionInt

      ernal(PreInstallAction.java:90)

              at org.jboss.kernel.plugins.dependency.InstallsAwareAction.installAction

      (InstallsAwareAction.java:54)

              at org.jboss.kernel.plugins.dependency.InstallsAwareAction.installAction

      (InstallsAwareAction.java:42)

              at org.jboss.dependency.plugins.action.SimpleControllerContextAction.sim

      pleInstallAction(SimpleControllerContextAction.java:62)

              at org.jboss.dependency.plugins.action.AccessControllerContextAction.ins

      tall(AccessControllerContextAction.java:71)

              at org.jboss.dependency.plugins.AbstractControllerContextActions.install

      (AbstractControllerContextActions.java:51)

              at org.jboss.dependency.plugins.AbstractControllerContext.install(Abstra

      ctControllerContext.java:348)

              at org.jboss.dependency.plugins.AbstractController.install(AbstractContr

      oller.java:1631)

              at org.jboss.dependency.plugins.AbstractController.incrementState(Abstra

      ctController.java:934)

              at org.jboss.dependency.plugins.AbstractController.resolveContexts(Abstr

      actController.java:1082)

              at org.jboss.dependency.plugins.AbstractController.resolveContexts(Abstr

      actController.java:984)

              at org.jboss.dependency.plugins.AbstractController.install(AbstractContr

      oller.java:774)

              at org.jboss.dependency.plugins.AbstractController.install(AbstractContr

      oller.java:540)

              at org.jboss.deployers.vfs.deployer.kernel.BeanMetaDataDeployer.deploy(B

      eanMetaDataDeployer.java:121)

              at org.jboss.deployers.vfs.deployer.kernel.BeanMetaDataDeployer.deploy(B

      eanMetaDataDeployer.java:51)

              at org.jboss.deployers.spi.deployer.helpers.AbstractSimpleRealDeployer.i

      nternalDeploy(AbstractSimpleRealDeployer.java:62)

              at org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer.deploy(

      AbstractRealDeployer.java:50)

              at org.jboss.deployers.plugins.deployers.DeployerWrapper.deploy(Deployer

      Wrapper.java:171)

              at org.jboss.deployers.plugins.deployers.DeployersImpl.doDeploy(Deployer

      sImpl.java:1439)

              at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFi

      rst(DeployersImpl.java:1157)

              at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFi

      rst(DeployersImpl.java:1178)

              at org.jboss.deployers.plugins.deployers.DeployersImpl.install(Deployers

      Impl.java:1098)

              at org.jboss.dependency.plugins.AbstractControllerContext.install(Abstra

      ctControllerContext.java:348)

              at org.jboss.dependency.plugins.AbstractController.install(AbstractContr

      oller.java:1631)

              at org.jboss.dependency.plugins.AbstractController.incrementState(Abstra

      ctController.java:934)

              at org.jboss.dependency.plugins.AbstractController.resolveContexts(Abstr

      actController.java:1082)

              at org.jboss.dependency.plugins.AbstractController.resolveContexts(Abstr

      actController.java:984)

              at org.jboss.dependency.plugins.AbstractController.change(AbstractContro

      ller.java:822)

              at org.jboss.dependency.plugins.AbstractController.change(AbstractContro

      ller.java:553)

              at org.jboss.deployers.plugins.deployers.DeployersImpl.process(Deployers

      Impl.java:781)

              at org.jboss.deployers.plugins.main.MainDeployerImpl.process(MainDeploye

      rImpl.java:702)

              at org.jboss.system.server.profileservice.repository.MainDeployerAdapter

      .process(MainDeployerAdapter.java:117)

              at org.jboss.system.server.profileservice.repository.ProfileDeployAction

      .install(ProfileDeployAction.java:70)

              at org.jboss.system.server.profileservice.repository.AbstractProfileActi

      on.install(AbstractProfileAction.java:53)

              at org.jboss.system.server.profileservice.repository.AbstractProfileServ

      ice.install(AbstractProfileService.java:361)

              at org.jboss.dependency.plugins.AbstractControllerContext.install(Abstra

      ctControllerContext.java:348)

              at org.jboss.dependency.plugins.AbstractController.install(AbstractContr

      oller.java:1631)

              at org.jboss.dependency.plugins.AbstractController.incrementState(Abstra

      ctController.java:934)

              at org.jboss.dependency.plugins.AbstractController.resolveContexts(Abstr

      actController.java:1082)

              at org.jboss.dependency.plugins.AbstractController.resolveContexts(Abstr

      actController.java:984)

              at org.jboss.dependency.plugins.AbstractController.change(AbstractContro

      ller.java:822)

              at org.jboss.dependency.plugins.AbstractController.change(AbstractContro

      ller.java:553)

              at org.jboss.system.server.profileservice.repository.AbstractProfileServ

      ice.activateProfile(AbstractProfileService.java:306)

              at org.jboss.system.server.profileservice.ProfileServiceBootstrap.start(

      ProfileServiceBootstrap.java:271)

              at org.jboss.bootstrap.AbstractServerImpl.start(AbstractServerImpl.java:

      461)

              at org.jboss.Main.boot(Main.java:221)

              at org.jboss.Main$1.run(Main.java:556)


      DEPLOYMENTS MISSING DEPENDENCIES:

        Deployment "CB1" is missing the following dependencies:

          Dependency "CustomCL" (should be in state "PreInstall", but is actually in s

      tate "**ERROR**")

       

       

      DEPLOYMENTS IN ERROR:

        Deployment "CustomCL" is in error due to the following reason(s): java.lang.Cl

      assNotFoundException: com.beans.CustomClassLoader, **ERROR**



      Can anyone help in solving this problem.

      From the above error, it seems that the baseClassLoader doesn't know where com.beans.CustomClassLoader is located.

       

      Thanks in advance,

      Irfan

        • 1. Re: Custom ClassLoader
          Ales Justin Master

          classloader element takes explicit roots -- paths to jars, etc.

          * http://anonsvn.jboss.org/repos/jbossas/projects/jboss-cl/branches/Branch_2_0/classloading-vfs/src/main/java/org/jboss/classloading/spi/vfs/metadata/VFSClassLoaderFactory.java

           

          Just create CustomCL bean -- no need for classloader element, and set this as classloader to other beans.

           

          Having classloader per whole deployment (whole -beans.xml) is a bit trickier,

          as it's chicken-n-egg problem.

          • 2. Re: Custom ClassLoader
            Ales Justin Master

            Your last post somehow got removed ...

             

            But no, completely remove <classloader name element.

            Plain CL bean should do.

            • 3. Re: Custom ClassLoader
              Irfan Basha Newbie

              Thanks Ales...

              I deleted the last post because I got it working soon after I posted it.

               

              Thanks once again...

               

              Regards,

              Irfan

              • 4. Re: Custom ClassLoader
                Ales Justin Master

                I deleted the last post because I got it working soon after I posted it.

                Can you post the solution, so others can learn as well?

                • 5. Re: Custom ClassLoader
                  Irfan Basha Newbie

                  Solution:

                   

                  1. Add jboss-beans.xml to WEB-INF:

                  <deployment xmlns="urn:jboss:bean-deployer:2.0">

                           <classloader name="custom-classloader" xmlns="urn:jboss:classloader:1.0"

                                      export-all="NON_EMPTY" import-all="true" />

                            <bean name="CustomCL" class="com.beans.CustomClassLoader">

                                      <constructor>

                                                <parameter>

                                                          <inject bean="custom-classloader:0.0.0" />

                                                </parameter>

                                      </constructor>

                            </bean>

                            <bean name="CB1" class="com.Sample">

                            <classloader>

                                      <inject bean="CustomCL" />

                            </classloader>

                  </bean>

                  </deployment>


                   

                  2. Create a CustomClassLoader (com.beans.CustomClassLoader):

                  public class CustomClassLoader extends ClassLoader

                  {

                     public CustomClassLoader(ClassLoader parent)

                     {

                        super(parent);

                     }

                     public Class<?> loadClass(String name) throws ClassNotFoundException

                     {    

                            //This simply calls super's loadClass (if run from jboss, it calls BaseClassLoader

                           return super.loadClass(name);    

                     }

                    

                  }

                   

                  Run JBoss, keep a breakpoint in CustomClassLoader.loadClass method. when class com.Sample has to be loaded the breakpoint will be hit.

                   

                  Regards,

                  Irfan

                  1 of 1 people found this helpful
                  • 6. Re: Custom ClassLoader
                    Ales Justin Master

                    Hmmm, how does CustomCL see com.Sample class?

                     

                    Afair, <classloader> then has zero roots, meaning it only sees system classpath.

                    Where your CustomCL is created in deployment's CL, with zero-root CL as parent,

                    where you then try to load com.Sample ... beats me. :-)

                     

                    Unless this zero-roots CL shares the same domain as deployment's CL.

                    • 7. Re: Custom ClassLoader
                      Irfan Basha Newbie

                      I guess the zero-roots CL (as you say) shares the domain of deployment's CL.

                       

                      Is that the reason why super.loadClass goes back to org.jboss.classloader.spi.base.BaseClassLoader ?

                       

                      Is there any thing wrong in what I did ? (I am able to get the breakpoint in loadClass method, and here the parent classloader is BaseClassLoader of jboss)

                       

                      What I am trying to do is:

                      My war has few encrypted classes (which can be decrypted only if a hardware dongle is available using the ClassLoader provided by the hardware dongle). And now since we use JBoss, the encrypted classes are not been loaded. (In tomcat it was possible to set the system classloader :  –Djava.system.class.loader in catalina.bat)

                      I first tried to load then using translator (the previous post from me), but if I use translator, the plain bytecode is available in translator (after translator decrypts the encrypted class)

                      So now I am trying to use this customClassLoader, and here use the ClassLoader provided the third party (the company which provides us the hardware dongle).

                      • 8. Re: Custom ClassLoader
                        Ales Justin Master


                        I guess the zero-roots CL (as you say) shares the domain of deployment's CL.

                        Can we somehow confirm this?

                         

                        Is that the reason why super.loadClass goes back to org.jboss.classloader.spi.base.BaseClassLoader ?

                        If 1st paragraph holds, then yes.

                         

                        Is there any thing wrong in what I did ? (I am able to get the breakpoint in loadClass method, and here the parent classloader is BaseClassLoader of jboss)

                         

                        From 10.000ft atm, no. :-)

                         

                        My war has few encrypted classes (which can be decrypted only if a hardware dongle is available using the ClassLoader provided by the hardware dongle). And now since we use JBoss, the encrypted classes are not been loaded. (In tomcat it was possible to set the system classloader :  –Djava.system.class.loader in catalina.bat)

                        I first tried to load then using translator (the previous post from me), but if I use translator, the plain bytecode is available in translator (after translator decrypts the encrypted class)

                        So now I am trying to use this customClassLoader, and here use the ClassLoader provided the third party (the company which provides us the hardware dongle).

                         

                        I don't see how translator is different from classloader.

                        In both cases you can see the actual bytecode.

                        • 9. Re: Custom ClassLoader
                          Irfan Basha Newbie

                          The translator is different from classloader:

                          If I use translator, I pass the encrypted bytecode to the translator and the translator decrypts it and sends back the actual bytecode. So once the translator decrypts it, the actual bytecode can be obtained easily. If anyone wants to get the actual bytecode, he/she can just get it from translator.

                          If I use classloader (provided by the third party security company, which decrypts the bytecode only if a hardware dongle is available), I just pass the classname to the ClassLoader and it returns me the Class after loading it. So with the Class, one cannot get the bytecode (at least thats what I believe). This secure ClassLoader somehow loads the class without calling the java.lang.ClassLoader, and the classloader itself is encrypted so it is pretty much safe. (I tested this by changing the code of java.lang.ClassLoader in rt.jar... surprisingly this secure classloader doesn't call the java.lang.ClassLoader... )

                          • 10. Re: Custom ClassLoader
                            Ales Justin Master

                            This secure ClassLoader somehow loads the class without calling the java.lang.ClassLoader

                            Hmmm, never heard of this, nor have some co-workers ...

                             

                            and the classloader itself is encrypted so it is pretty much safe

                            How is then classloader decrypted?

                            Chicken-n-egg ...

                             

                            Afaik, any JavaAgent should be able to read the bytes.

                            Unless there is some JVM extension / magic I don't know about.

                            • 11. Re: Custom ClassLoader
                              Irfan Basha Newbie

                              Well, I must agree that I have just about 2 years of experience in java programming... and as far as my knowledge is, for java to execute a class it should first load it in memory (in jvm) and this can be done by ClassLoader. Hence any class which should be loaded should have gone through loadClass method of ClassLoader. (I suppose this also applies for classes loaded through reflection)

                               

                              And the strange thing is, when I modified the code of java.lang.ClassLoader and dumped the bytecode to my local disk (from method loadClass), I didnot find the classes which are loaded through the secure classloader. Is there a way to load class into jvm from any other way without using java.lang.ClassLoader ?

                              • 12. Re: Custom ClassLoader
                                Ales Justin Master

                                Is there a way to load class into jvm from any other way without using java.lang.ClassLoader ?

                                Not that I'm aware of.

                                But I never looked JVM into details.

                                • 13. Re: Custom ClassLoader
                                  Irfan Basha Newbie

                                  Anyway, Is there a way to extend the org.jboss.classloader.spi.base.BaseClassLoader ?

                                  • 14. Re: Custom ClassLoader
                                    Ales Justin Master

                                    The idea behind extending MC's CL layer is to provide CL policy.

                                    All ugly details are hidden behind CL policy usage.

                                    1 2 Previous Next