Showing posts with label classloaders. Show all posts
Showing posts with label classloaders. Show all posts

Friday, November 11, 2016

verbose:class not tracing the classloader

If you start the jvm with "java -verbose:class" you get this stuff:

[Opened c:\pippo\wl12.1\oracle_common\modules\endorsed\javax-xml-bind.jar]
[Opened c:\pippo\wl12.1\oracle_common\modules\endorsed\javax-xml-ws.jar]
[Opened c:\pippo\wl12.1\oracle_common\modules\endorsed\jsr250-api.jar]
[Opened c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.Object from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.io.Serializable from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.Comparable from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.CharSequence from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.String from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.reflect.Type from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.Class from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.Cloneable from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.ClassLoader from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.System from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.Throwable from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.Error from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.ThreadDeath from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.Exception from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.RuntimeException from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.security.ProtectionDomain from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.security.AccessControlContext from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.ReflectiveOperationException from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.ClassNotFoundException from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.LinkageError from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.NoClassDefFoundError from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.ClassCastException from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.ArrayStoreException from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.VirtualMachineError from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.OutOfMemoryError from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]
[Loaded java.lang.StackOverflowError from c:\pippo\java\jdk170_101-64b\jre\lib\rt.jar]


but this is not enough to discover nasty classloader issues. I have searched the Planet but apparently there is no way to print also the classloader without with Java OOTB.

This is a lot better:

https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5

and I copy the code here just in case:

import java.lang.instrument.*;

import java.security.*;

 

public class ClassLoadTracer {

    public static void premain(String agentArgs, Instrumentation inst) {

         final java.io.PrintStream out = System.out;

         inst.addTransformer(new ClassFileTransformer() {

             public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

                 out.print(className + " loaded by " + loader + " at " + new java.util.Date());

                 out.println(" in " + protectionDomain);
// dump stack trace of the thread loading class
//        Thread.dumpStack();

                 // we just want the original .class bytes to be loaded!
                 // we are not instrumenting it...
                 return null;
             }
         });
    }
}

 



and you get this:


sun/launcher/LauncherHelper loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

sun/nio/cs/MS1252 loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

sun/nio/cs/SingleByte loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

sun/nio/cs/SingleByte$Decoder loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

java/lang/Package loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

weblogic/Server loaded by sun.misc.Launcher$AppClassLoader@2792e317 at Fri Nov 11 10:48:52 CET 2016 in ProtectionDomain  (file:/c:\pippo\wl12.1/wlserver/modules/features/weblogic.server.merged.jar <no signer certificates>)
sun.misc.Launcher$AppClassLoader@2792e317
<no principals>
java.security.Permissions@54a01a10 (
("java.lang.RuntimePermission" "exitVM")
("java.io.FilePermission" "\c:\pippo\wl12.1\wlserver\modules\features\weblogic.server.merged.jar" "read")
)

java/lang/Void loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

utils/ValidateJavaEE6EndorsedOverrides loaded by sun.misc.Launcher$AppClassLoader@2792e317 at Fri Nov 11 10:48:52 CET 2016 in ProtectionDomain  (file:/c:\pippo\wl12.1/wlserver/modules/features/weblogic.server.merged.jar <no signer certificates>)
sun.misc.Launcher$AppClassLoader@2792e317
<no principals>
java.security.Permissions@54a01a10 (
("java.lang.RuntimePermission" "exitVM")
("java.io.FilePermission" "\c:\pippo\wl12.1\wlserver\modules\features\weblogic.server.merged.jar" "read")
)

weblogic/security/utils/SecurityUtils loaded by sun.misc.Launcher$AppClassLoader@2792e317 at Fri Nov 11 10:48:52 CET 2016 in ProtectionDomain  (file:/c:\pippo\wl12.1/wlserver/modules/features/weblogic.server.merged.jar <no signer certificates>)
sun.misc.Launcher$AppClassLoader@2792e317
<no principals>
java.security.Permissions@54a01a10 (
("java.lang.RuntimePermission" "exitVM")
("java.io.FilePermission" "\c:\pippo\wl12.1\wlserver\modules\features\weblogic.server.merged.jar" "read")
)

java/security/Security loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

java/security/Security$1 loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

java/util/Properties$LineReader loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

sun/security/util/PropertyExpander loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

sun/net/ProgressMonitor loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

sun/net/DefaultProgressMeteringPolicy loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

sun/net/ProgressMeteringPolicy loaded by null at Fri Nov 11 10:48:52 CET 2016 in null

weblogic/security/SecurityLogger loaded by sun.misc.Launcher$AppClassLoader@2792e317 at Fri Nov 11 10:48:52 CET 2016 in ProtectionDomain  (file:/c:\pippo\wl12.1/wlserver/modules/features/weblogic.server.merged.jar <no signer certificates>)
sun.misc.Launcher$AppClassLoader@2792e317
<no principals>
java.security.Permissions@54a01a10 (
("java.lang.RuntimePermission" "exitVM")
("java.io.FilePermission" "\c:\pippo\wl12.1\wlserver\modules\features\weblogic.server.merged.jar" "read")
)



The protection domain info is way too verbose, and probably you want to be able to control/filter better the output, otherwise it gets really too verbose.... but this seems to be really a big step forward...

You can use multiple agents:

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/instrument/package-summary.html

 

On JVMs with a command-line interface, agents are specified by adding 
this switch to the JVM command-line:

-javaagent:jarpath[=options]

jarpath is the path to the agent JAR file. options is the agent options. 
This switch may be used multiple times on the same command line,
thus creating multiple agents. More than one agent may use the same jarpath.



Friday, January 15, 2016

Same classloader for EJB and WAR

https://docs.oracle.com/middleware/1212/wls/WLPRG/classloading.htm#WLPRG293

you can alter the weblogic-application.xml with this

<classloader-structure> 
    <module-ref> 
       <module-uri>ejb1.jar</module-uri> 
    </module-ref>
    <module-ref> 
       <module-uri>web1.war</module-uri> 
    </module-ref>
 </classloader-structure> 


however it's recommended to either put your shared classes in APP-INF/lib, or remove circular dependencies if any

Sunday, October 25, 2015

ContextClassLoader, SystemClassLoader, CurrentClassLoader

If you run this code as a Java Application (no JEE container):

public class BootstrapCLTest {
    public static void main(String[] args) {
 BootstrapCLTest bootstrapCLTest = new BootstrapCLTest();
 bootstrapCLTest.go();
    }

    private void go() {

 System.out.println("1 " + String.class.getClassLoader());
 System.out.println("2 " + ClassLoader.getSystemClassLoader ());
 System.out.println("3 " + this.getClass().getClassLoader());
 System.out.println("4 " + Thread.currentThread().getContextClassLoader());
 System.out.println("5 " + Thread.currentThread().getContextClassLoader().getParent());
 System.out.println("6 " + Thread.currentThread().getContextClassLoader().getParent().getParent());
    }

}



you get this (parentesis are mine):

1 null (=bootstrap CL)
2 sun.misc.Launcher$AppClassLoader@1bd06bf (=application CL)
3 sun.misc.Launcher$AppClassLoader@1bd06bf (=application CL)
4 sun.misc.Launcher$AppClassLoader@1bd06bf (=application CL)
5 sun.misc.Launcher$ExtClassLoader@1061299 (=extension CL)
6 null (=bootstrap CL)


that is, in this simple case the SystemClassLoader == ApplicationClassLoader == ContextClassLoader

The first null is because the String class is loaded by the Bootstrap classloader, which is NOT represented as a ClassLoader object. The Bootstrap will then load the Extension CL, who in turn loads the Application CL.

Running a similar code in a JSP is more interesting, because here the JEE container (WebLogic in this case) will add its own CL:

 System.out.println("1 " + String.class.getClassLoader());
 System.out.println("2 " + ClassLoader.getSystemClassLoader ());
 System.out.println("3 " + this.getClass().getClassLoader());
 System.out.println("4 " + Thread.currentThread().getContextClassLoader());
 System.out.println("5 " + Thread.currentThread().getContextClassLoader().getParent());
 System.out.println("6 " + Thread.currentThread().getContextClassLoader().getParent().getParent());
 System.out.println("7 " + Thread.currentThread().getContextClassLoader().getParent().getParent().getParent());
 System.out.println("8 " + Thread.currentThread().getContextClassLoader().getParent().getParent().getParent().getParent());
 System.out.println("9 " + Thread.currentThread().getContextClassLoader().getParent().getParent().getParent().getParent().getParent());
 System.out.println("10 " + Thread.currentThread().getContextClassLoader().getParent().getParent().getParent().getParent().getParent().getParent());


the result is:

1 null
2 sun.misc.Launcher$AppClassLoader@fc5b01
3 weblogic.servlet.jsp.JspClassLoader@1bfdb6f finder: weblogic.utils.classloaders.CodeGenClassFinder@137e701 annotation:
4 weblogic.utils.classloaders.ChangeAwareClassLoader@1cc3dd4 finder: weblogic.utils.classloaders.CodeGenClassFinder@11f2691 annotation: _auto_generated_ear_@CLTestWeb
5 weblogic.utils.classloaders.FilteringClassLoader@1d16e3 finder: weblogic.utils.classloaders.CodeGenClassFinder@1c9a7b5 annotation: _auto_generated_ear_@CLTestWeb
6 weblogic.utils.classloaders.GenericClassLoader@ceb98d finder: weblogic.utils.classloaders.CodeGenClassFinder@217181 annotation: _auto_generated_ear_@
7 weblogic.utils.classloaders.FilteringClassLoader@1a308be finder: weblogic.utils.classloaders.CodeGenClassFinder@92f8f0 annotation:
8 weblogic.utils.classloaders.GenericClassLoader@1865594 finder: weblogic.utils.classloaders.CodeGenClassFinder@fcfe6b annotation:
9 sun.misc.Launcher$AppClassLoader@fc5b01
10 sun.misc.Launcher$ExtClassLoader@1353d27

that is, WebLogic inserts 2 layers of GenericClassLoader or ChangeAwareClassLoader plus FilteringClassLoader between the War Application and the System Classloader.

See also http://www.javamonamour.org/2015/09/playing-with-cat-and-classloaders.html



Sunday, September 20, 2015

Playing with CAT and classloaders

tutorial video here:




I was reading the excellent Oracle document http://docs.oracle.com/middleware/1212/wls/WLPRG/classloading.htm#WLPRG320 on classloaders - very nice but it misses pictures and real data.

So I have created a EAR PVEar, and inside a Stateless EJB, an EJBClient (and a PVTimer, ignore it) and a WebApp


I open the cat tool, analyze the PVEar, click on "detailed", and I get this:
System Classloaders


 Type: sun.misc.Launcher$ExtClassLoader
HashCode: 22293724
Classpath:

    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/access-bridge-32.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/access-bridge.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/dnsns.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/jaccess.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/localedata.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/sunec.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/sunjce_provider.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/sunmscapi.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/sunpkcs11.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/jre/lib/ext/zipfs.jar

Type: sun.misc.Launcher$AppClassLoader
HashCode: 27035333
Classpath:

    /D:/Oracle/Middleware/Oracle_Home/oracle_common/jdk/lib/tools.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/modules/com.oracle.cie.config-wls-online_8.1.0.0.jar
    /D:/Oracle/Middleware/Oracle_Home/oracle_common/modules/net.sf.antcontrib_1.1.0.0_1-0b3/lib/ant-contrib.jar
    /D:/Oracle/Middleware/Oracle_Home/wlserver/common/derby/lib/derby.jar
    /D:/Oracle/Middleware/Oracle_Home/wlserver/common/derby/lib/derbyclient.jar
    /D:/Oracle/Middleware/Oracle_Home/wlserver/common/derby/lib/derbynet.jar
    /D:/Oracle/Middleware/Oracle_Home/wlserver/modules/features/oracle.wls.common.nodemanager_2.0.0.0.jar
    /D:/Oracle/Middleware/Oracle_Home/wlserver/server/lib/weblogic.jar
    /D:/Oracle/Middleware/Oracle_Home/wlserver/server/lib/weblogic_sp.jar
    /D:/Oracle/Middleware/Oracle_Home/wlserver/server/lib/xqrl.jar

Type: weblogic.utils.classloaders.GenericClassLoader
HashCode: 21751181
Classpath:



Application Classloaders



Type: weblogic.utils.classloaders.FilteringClassLoader
HashCode: 10170360
Filter: []
Classpath: empty
Type: weblogic.utils.classloaders.GenericClassLoader
HashCode: 1771581
Classpath:

    D:\pierre\domains\pvdomain\servers\AdminServer\cache\EJBCompilerCache\h8uvtcz3nyfq
    D:\pierre\workspace12c\PVEar\EarContent\APP-INF\classes
    D:\pierre\workspace12c\PVEjbProjectClient\build\classes
    D:\pierre\workspace12c\PVEjbProject\build\PVEjbProjectClient.jar
    D:\pierre\workspace12c\PVEjbProject\build\classes




clicking on the EJB module I get exactly the same picture. But on the WebApp module I get an extra FilteringClassLoader:
Application Classloaders

(this one is same as in the EJB)

Type: weblogic.utils.classloaders.FilteringClassLoader
HashCode: 10170360
Filter: []
Classpath: empty
Type: weblogic.utils.classloaders.GenericClassLoader
HashCode: 1771581
Classpath:

    D:\pierre\domains\pvdomain\servers\AdminServer\cache\EJBCompilerCache\h8uvtcz3nyfq
    D:\pierre\workspace12c\PVEar\EarContent\APP-INF\classes
    D:\pierre\workspace12c\PVEjbProjectClient\build\classes
    D:\pierre\workspace12c\PVEjbProject\build\PVEjbProjectClient.jar
    D:\pierre\workspace12c\PVEjbProject\build\classes


(this one is new)

Type: weblogic.utils.classloaders.FilteringClassLoader
HashCode: 6976334
Filter: []
Classpath: empty
Type: weblogic.utils.classloaders.ChangeAwareClassLoader
HashCode: 12727142
Classpath:

    D:\pierre\workspace12c\PVWeb\build\classes





So, the FilteringClassLoader 10170360 separates from the System Classloader ANYTHING inside the EAR module.
The FilteringClassLoader 6976334 separates the WebApp from the EAR.WebApp and EJB share the same Application Classloaders GenericClassLoader 1771581.



Saturday, August 14, 2010

FilteringClassLoader

This article on ClassLoaders in WebLogic is extremely interesting:

http://download.oracle.com/docs/cd/E12840_01/wls/docs103/programming/classloading.html

I have taken some notes:

bootstrap classloader
extensions classloader
system classpath classloader

application classloaders
(EAR: root classloader for EJBs, child classloader for each WAR)

in weblogic-application.xml with classloader-structure you can customize the classloaders

APP-INF/lib

manifest Class-Path entry

when 2 modules share the same classloader, call by reference is possible. Otherwise call-by-value is used.

classes in $CLASSPATH are always loaded before than whose in application classpath, unless you specify a FilteringClassLoader.
a FilteringClassLoader allows you to load classes locally to your classloader
add prefer-application-packages descriptor element to the weblogic-application.xml