I have this code
MyClassloader loader = new MyClassloader();
Class c = loader.loadClass(classToLoad);
Thread.currentThread().setContextClassLoader(loader);
MyClass myClass = (MyClass) c.newInstance();
And classloader code is
public MyClassloader) throws IOException {
super(Thread.currentThread().getContextClassLoader());
}
The class loading works fine the problem is that static variables are not isolated, so if inside the MyClass a static variable is set all other MyClass instances get the same value.
In what can a static variable be isolated?
You delegate to the same class loader. So you will see no difference.
What should yo do? Implement class loading in your class loader, don't just delegate. For instance, inherit your class loader from URLClassLoader, initialize it properly (it means, provide a valid class path to your class loader to initialize it). Then you will see, that classes loaded by you class loader are not euqal to the classes loaded by the standard class loader, and as a consequence, their static members will be different.
Often the context class loader is inherited from URLClassLoader and thus you don't have to spend much time configuring class path for it. Instead, to initialize you class loader you can just reuse the URLs of the context class loader, as follows:
public class MyIndependentClassLoader extends URLClassLoader {
public MyIndependentClassLoader(){
super(((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs());
}
}
Now you can use your class loader and check static members.
What is the difference between this approach and the original approach?
You know that classes are also objects (of special type): they have their own member variables, name, serialVersionUID, annotationData, etc., and their own methods, newInstance(), getFields(), getMethods(), etc. When you call
Class c = loader.loadClass("com.my.package.MyClassX");
you get c, this is an object that describes the loaded class "some class name". This c not only allows to create instances, but holds also all static members.
In your code: Your class loader does not load class directly. Instead, it delegates to the context class loader. That's why if you compare two loaded classes
Class c = loader.loadClass("com.my.package.MyClassX");
Class ct = Thread.currentThread().getContextClassLoader().loadClass("com.my.package.MyClassX");
you will see, that c and ct is the same object. If you call c.equals(ct), it will give you true. And if you call c == ct, it will also give you true. It means, this is the same class instance. That's why - naturally - if you check static variables, they will be the same. If you change static variable in one class, it will also be changed in another class, and vice versa.
In my code: The essential difference is, that the class loader loads classes itself. It does not delegate it to other class loader. I suggested to extend it from URLClassLoader to simplify our implementation (otherwise you would have implement from scratch dealing with class path, directories, jars, visibility, caching, etc.). And to avoid adding each class path element step by step I suggested to use the same class path (the same list of directories, jars, etc.) as the context class loader. So our class loader will be able to find the same classes as the context class loader.
Now check the class that this class loader loads. Let's call it ci:
Class ci = new MyIndependentClassLoader().loadClass("com.my.package.MyClassX");
If you compare these classes, you will see that c.equals(ci) gives false. Means, they are different. That's why they have also independent static members. If you change static member in one class, ct, it will not change in the other, ci, and vice versa.
Related
I create my custom class loader :
new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
where urls is a new Url("java.util.TimeZone")
After that I load class by name :
Class<?> newTimeZoneClass = loader.loadClass("java.util.TimeZone");
and newTimeZoneClass==TimeZone.class returns true.
The main reason of that my class loader load class from parent loader.
How to fix it?
You cannot do this. The Java security model prevents any class loader creating a class in the "java.*" hierarchy. This is hard-coded in the native code of the JVM, so there is no workaround.
Additionally, the standard class loaders follow the delegation model of asking the parent class loader to load the class before they try to, so you always get the same class instance. Special class loaders are used by application containers to invert this delegation for application specific classes.
There are a few ways to do this anyway.
First, TimeZone is an abstract class and the actual implementation is normally sun.util.calendar.ZoneInfo. As this is not in the "java.*" hierarchy, you can create multiple copies in your class loaders.
Second, you can sub-class TimeZone, and delegate all methods to a JVM provided instance, adding your own functionality as you do so. I've used this to make TimeZone instances singletons in some of my applications.
Third, as the JDK is open source, you can copy the all the code for TimeZone and its sub-classes into your own application, and then you can have as many versions of the class as you like.
If you want to change the TimeZone instances returned by the static methods in TimeZone, these delegate to ZoneInfo and you will have to either use reflection to change the outcome. If you know Aspect-J or equivalent, you could also intercept the call.
As it is mentioned in Java Doc of public URLClassLoader(URL[] urls, ClassLoader parent):
Constructs a new URLClassLoader for the given URLs. The URLs will be
searched in the order specified for classes and resources after first
searching in the specified parent class loader.
I assume you should create a CustomClassLoader ccl = new CustomClassLoader(); or use another constructor by passing an AccessControlContext object - URLClassLoader(URL[] urls, ClassLoader parent, AccessControlContext acc)
or URLClassLoader(URL[] urls, AccessControlContext acc).
There are some articles on creating new class loaders:
https://www.baeldung.com/java-classloaders
https://www.javaworld.com/article/2077260/learn-java-the-basics-of-java-
https://www.oodlestechnologies.com/blogs/Creating-Custom-Class-Loader-In-JAVA/class-loaders.html
I know that super will be called every time we create a child class object. But, what I specifically want to know is that will it load the class or will it create the object of that parent class.
Thanks in advance.
You have a single object.
As a class is instantiated, it invokes first the constructor of the parent class. And for each parent class, it follows the same logic : it invokes first the constructor of the parent class.
Suppose : A extends B extends C.
new A() results to the B constructor invocation that invokes itself the C constructor.
As C then B constructor invocations are returned, the A constructor can go on and the instance A is created.
But, what I specifically want to know is that will it load the class
or will it create the object of that parent class.
Similarly to the constructor execution, before loading a class, its parent class has to be loaded first and that recursively for each parent class.
Here classes corresponding to A extends B extends C :
class C {
public C(){
System.out.println("C constructor");
}
}
class B extends C{
public B() {
System.out.println("B constructor");
}
}
class A extends B{
public A() {
System.out.println("A constructor");
}
}
public class Test {
public static void main(String[] args) {
new A();
}
}
Compile these classes and then execute the Test class that creates a A instance in its main() method by specifying the -verbose flag (enable by default the classes logs) in the java command :
java -verbose Test
And you should see in the output standard something like :
[Loaded java.lang.Object from C:\...]
[Loaded java.io.Serializable from C:\...]
... // load all classes required until loaded C, B and A classes
[Loaded C from file:/C:/...]
[Loaded B from file:/C:/...]
[Loaded A from file:/C:/...]
C constructor
B constructor
A constructor
It confirms that :
the parent classes need to be loaded first by starting by the root parent class ( Object) until the closest parent class(B).
no constructor is executed before all classes of the hierarchy be loaded
the constructors of the parent classes are always executed before the constructor of the instantiated class by starting by the root parent constructor ( Object) until the closest parent constructor(B).
The constructor is called, therefore an object of the parent class is created. That object is used later to build an object of the child class. The reason for this is that an object of the child class is an object of the parent class with more things.
Because the child class inherits properties and methods from the parent class, the entire class hierarchy (including superclasses and implemented interfaces) are loaded.
When you create an instance of the childclass, only a single object of type childclass is created (instantiated). There are no additional instances of any parent(s).
The properties and methods declared on parent classes are accessible via the childclass instance, and due to this inheritance the childclass instance will be accepted as argument to any methods that expect an instance of the parent (or any interfaces that it or any parent implements).
If you think of the code as a contractual design, this makes perfect sense:
The parent class declaration establishes that certain methods are available to call on itself or any of its children. The same is true for interfaces. For example, all employment contracts in the real world must contain certain clauses, but the rest is up to the company.
By inheriting (extends or implements) it is guaranteed that the child will also automatically provide the same methods. For example, we can assume that any law-abiding company will provide employment contracts including those clauses and (once agreed) the signature of both you and the company.
The entire hierarchy needs to be loaded in order to understand the full contract.For example, if there is a dispute, the lawyers who examine a contract will check what the law prescribes, perhaps by looking at a sample contract provided by the legislating body. The parentClass is that sample in the problem.
We only need one object instance. For example you won't get two employment contracts, one for the basic stuff and another with more information. You will receive and sign a single document.
Finally, in my analog, any employment contract (no matter how it is phrased) will be acceptable to any agency that asks you to prove your relationship to the company that employs you (assuming it is legal and valid by containing the legally prescribed clauses and appropriate signatures).
When you first load a class, all its ancestors are also loaded recursively.
When you instantiate an object you won't instantiate an additional instance of its parent. However, the object you just instantiated is itself also an instance of the parent.
I'm trying to understand why the JVM decides to load certain classes when it doesn't appear it needs to. Consider the following example code:
public class Foo {
public void foo() {
}
static class Bar {
}
public Bar bar() {
return new Bar();
}
}
When calling new Foo().foo(), Bar is not loaded by the classloader since it's not needed. But, if we change the example to have bar return an instance of a sub-class:
public class Foo {
public void foo() {
}
static class Bar {
}
static class BigBar extends Bar {
}
public Bar bar() {
return new BigBar();
}
}
Calling new Foo().foo() causes the classloader to load both the Bar and BigBar classes even though neither of them are needed. Why?
Aside from this specific scenario, is there a way to learn why the JVM decides it needs to load a class, in general?
Here is a good read from Internals of Java Class Loading
Whenever a new JVM is started by typing java MyMainClass, the
"bootstrap class loader" is responsible for loading key Java classes
like java.lang.Object and other runtime code into memory first. The
runtime classes are packaged inside of the JRE\lib\rt.jar file. We
cannot find the details of the bootstrap class loader in the Java
documentation, since this is a native implementation. For the same
reason, the behavior of the bootstrap class loader will also differ
across JVMs.
In a related note, we will get null if we try to get the class loader
of a core Java runtime class, like this:
log(java.lang.String.class.getClassLoader());
Next comes the Java extension class loader. We can store extension
libraries, those that provide features that go beyond the core Java
runtime code, in the path given by the java.ext.dirs property. The
ExtClassLoader is responsible for loading all .jar files kept in the
java.ext.dirs path. A developer can add his or her own application
.jar files or whatever libraries he or she might need to add to the
classpath to this extension directory so that they will be loaded by
the extension class loader.
The third and most important class loader from the developer
perspective is the AppClassLoader. The application class loader is
responsible for loading all of the classes kept in the path
corresponding to the java.class.path system property.
well explained http://javarevisited.blogspot.in/2012/07/when-class-loading-initialization-java-example.html
When Class is loaded in Java
Class loading is done by ClassLoaders in Java which can be implemented to eagerly load a class as soon as another class references it or lazy load the class until a need of class initialization occurs. If Class is loaded before its actually being used it can sit inside before being initialized. I believe this may vary from JVM to JVM. While its guaranteed by JLS that a class will be loaded when there is a need of static initialization.
When a Class is initialized in Java
1) an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
2) an static method of Class is invoked.
3) an static field of Class is assigned.
4) an static field of class is used which is not a constant variable.
5) if Class is a top level class and an assert statement lexically nested within class is executed.
Could someone explain what is the difference between Class loading and instantiating a Class. When we load a class with Static variable does it also get instantiated the same time the Class get loaded? After all static code is part of the class rather than it's individual instances. It would be helpful if someone provided an example to help me understand this better.
Here is some nice explanation(with an example and observation)
When a class is loaded and initialized in JVM - Java
When Class is loaded in Java
Class loading is done by ClassLoaders in Java which can be implemented to eagerly load a class as soon as another class references it or lazy load the class until a need of class initialization occurs. If Class is loaded before its actually being used it can sit inside before being initialized. I believe this may vary from JVM to JVM. While its guaranteed by JLS that a class will be loaded when there is a need of static initialization.
When a Class is initialized in Java
When a Class is initialized in Java
After class loading, initialization of class takes place which means initializing all static members of class. A Class is initialized in Java when :
1) an Instance of class is created using either new() keyword or
using reflection using class.forName(), which may throw
ClassNotFoundException in Java.
2) an static method of Class is invoked.
3) an static field of Class
is assigned.
4) an static field of class is used which is not a
constant variable.
5) if Class is a top level class and an assert
statement lexically nested within class is executed.
Hope that helps.
Integer.toString(123);
For the above static method call to work, the Integer class must be loaded.
Integer i = new Integer(123);
And in the above code, I've created an instance (object) of the Integer class (which must also be loaded for this to work, obviously).
Some classes are not meant to be instantiated (like the Math class, for example, which only has static methods).
Class loading
Whenever the JVM determines it needs a class (to use its static variables, to create a new object, to use its static methods etc) it will load the class and static initialisation blocks will run, static variables are initialised etc. This is (at least under normal circumstances) done only once
SomeClass.someStaticMethod(); //SomeClass is loaded (if its not already)
SomeClass.someStaticVariable; //SomeClass is loaded (if its not already)
SomeClass var=new SomeClass(); //SomeClass is BOTH loaded (if its not already) AND instantiated
As a result the following runs (as an example):
static Vector3d var=new Vector3d(); //static variables are initialised
static{
//static initialisation block are run
}
Instantiating a class
On the other hand you instantiate a class when you create an instance of the class with the new keyword; instantiating a class is creating an object of the class.
SomeClass var=new SomeClass(); //SomeClass is instantiating (and loaded if its not already)
As a result the constructor runs:
public SomeClass(){
}
and
{
//initialisation block(s) also run (but these are very uncommonly used)
}
Class loader actually loads byte code into JVM , runs static initializers.When you want to use static fields within class without creating instance of it ,class must be loaded by class loader first.Default classloader in java is java.lang.ClassLoader.This class loading is done only once.
While class instantiation is creating instance of class into memory.We can instantiate class using new.Class instantiation can be done as many times.
eg: Animal a=new Animal();
More on class loading
A class is loaded when it is referenced (e.g. by Class.forName()).
You instanciate an object by creating an instance, e.g.
Object o = new Object();
You can also instanciate an object by using reflection.
static members of a class are instanciated when the class is loaded, e.g.
public class Sample {
private static int variable = 10;
}
When I now load the class (e.g. by Class.forName("Sample");) Then the variable variable is initialized with the value 10.
If you are creating a new instance of a class and it is not loaded before the class will be loade before (atomatically). So the construct Class.forName() is only needed under special circumstances (if the class is not known by compile time e.g.).
If I declare a variable static and compiled this class into a executable jar. If I start this class using batch file like this:
java MyClass
java MyClass
java MyClass
Would all 3 process share the same variable?
No. The static variable is specific to the JVM instance. More than that, in fact - it's specific to the class loader which loads the class. So if you created three separate class loaders, each responsible for loading MyClass (not just delegating to some common parent) they'd each have a separate, independent static variable in MyClass.
Static resources are per class loader and therefore, your 3 processes have obviously three different class loaders and hence, would not share the variables.