Question one:
Is ClassLoader.getSystemResource("img.png");
exactly same as ClassLoader.getSystemClassLoader().getResource("img.png");
and what is the difference (which one to prefer?). I am expecting the answer "don't use either" (inside app servers), so what for do we have these methods in the API?
Question two:
Having my WAR/app in Tomcat/other AppServer, shall I just always use Thread.currentThread().getContextClassLoader().getResourceAsStream("img.png")
without thinking of any use-cases where something else is more appropriate (say, objOfMyOwnClassCreatedAnywhereWithinMyApp.getClass().getClassLoader().getResource("sth")
?
Summing up what I know:
ClassLoader.getSystemResource("img.png");
vs
ClassLoader.getSystemClassLoader().getResource("img.png");
vs
Thread.currentThread().getContextClassLoader().getResource("sth");
My.class.getClassLoader().getResource("sth");
obj.getClass().getClassLoader().getResource("sth");
obj.getClass().getClassLoader().getSystemClassLoader().getResource("sth");
My.class.getClass().getClassLoader().getSystemClassLoader().getResource("sth");
Is my understanding correct:
1) In any application server (including Tomcat) I shall use only Thread.currentThread().getContextClassLoader().getResourceAsStream("NoSlash!_Img.png");
1.1) I shall never use any of the rest (on any app server)
2) On a desktop application all of the above are equivalent
3) Tomcat itself (class containing main() - entry point of Tomcat) is loaded with System class loader - which can always (100% ?) be identified with ClassLoader.getSystemClassLoader()
What is System.setProperty("java.system.class.loader")
is unclear to me. Besides, obj.getClass().getClassLoader().getSystemClassLoader()
shall also return same as ClassLoader.getSystemClassLoader()
, but it may return null
(if implementor of custom classloader decide they'd better not expose System Classloader). Beside null and real System ClassLoader obj.getClass().getClassLoader().getSystemClassLoader()
may not return anything else (because returning some other classloader would be stupid?).
4) Any Web application ( = context = WAR) within Tomcat / another app-server is loaded with its individual (custom) class loader (sometimes called "application class loader", which confuses it with "system class loader" sometimes also called "application class loader"). If I am within A class method, calling this.getClass().getClassLoader()
gives me the (custom) class-loader that loaded my class A (and my entire WAR / application).
So why shall I use Thread.currentThread().getContextClassLoader().getResource("sth")
instead of this.getClass().getClassLoader().getResource("sth")
? I thought that using my WAR custom classloader is best !
Is context class loader always same in all threads of my WAR (unless I start threads and mess with context class loaders myself) and is same as custom class loader which loaded my WAR (objOfMyOwnClassesCreatedAnywhereWithinMyApp.getClass().getClassLoader()
)?
Links studied: this, this, this
P.S. the answer here implies one situation where I shall prefer using context classloader. It means it is fine not to use context class loader in many other situations (when an object created on my thread is not given to any other thread, especially to such other thread that were not created by me).
Each class will use its own classloader to load other classes. So if ClassA.class references ClassB.class then ClassB needs to be on the classpath of the classloader of ClassA, or its parents.
The thread context classloader is the current classloader for the current thread. An object can be created from a class in ClassLoaderC and then passed to a thread owned by ClassLoaderD. In this case the object needs to use Thread.currentThread().getContextClassLoader() directly if it wants to load resources that are not available on its own classloader.
Besides Stackoverflow answer here (@yonran) recommends:
never use the context class loader!