Use of forName and GetClassLoader - java

When I read the documentation about Class, as to forName() method, the documentation said:
Class.forName ("Foo")
is equivalent to:
Class.forName ("Foo", true, this.getClass().GetClassLoader())
I don't know what the meaning of this.getClass().GetClassLoader() and why it works in this way, I just know it is a ClassLoader to load class when JVM complier the code.

A ClassLoader is an object capable of loading bytecode as a class into the VM. See here for the offical docs.
Class.forName(String name) allows you to load a class at runtime - the supplied String can by determined at runtime. To actually load a class one needs a ClassLoader thus it was chosen that the ClassLoader the class of the calling object was loaded with is the default one. You access that ClassLoader with this.getClass().getClassLoader().
The second parameter - defaulting to true - determines if static intialization is performed for the class if necessary (if it hasn't been performed earlier).

class.forName returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:
Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.

Related

Is a Java Class instance singleton?

According to the Java 8 Language Spec §15.8.2 (quote):
[...]
A class literal evaluates to the Class object for the named type (or for void) as defined by the defining class loader (§12.2) of the class of the current instance.
[...]
Mainly, 'the Class object' insinuates that this is or should be a singleton. Also §12.2 says:
[...]
Well-behaved class loaders maintain these properties:
Given the same name, a good class loader should always return the same class object.
[...]
In fact, using Java 8*, the following** prints true and true:
class Main {
public static void main(String[] args) {
Main main1 = new Main();
Main main2 = new Main();
System.out.println(main1.getClass().equals(main2.getClass()));
System.out.println(main1.getClass() == main2.getClass());
}
}
Is the class loader always 'well-behaved' and why (not)? In other words: are Class instances singleton? The other way around: can a Class of the same type be a different instance?
Notes: I do not refer to the singleton pattern here. However, if the Class implementation follows that pattern, that would be interesting. As a side-step, but by no means the main question: because the singleton pattern's legitimate uses are point of debate, would Java's Class be a good candidate to apply the singleton pattern to?
*:
$ java -version
openjdk version "1.8.0_262"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_262-b10)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.262-b10, mixed mode)
**: my IDE even warns me that the printed expressions are always true.
You are using the term singleton incorrectly.
A singleton implies the existence of only one object of its own class. A Class object is an instance of the class java.lang.Class and there is more than one instance of this class. It’s actually impossible to have only one Class object, as the existence of a Class object does already imply the existence of at least two classes, java.lang.Object and java.lang.Class, so there must be at least two Class objects in the runtime.
Your example is not capable of spotting whether the class loader is well behaved or not. You already mentioned JLS §12.2
Well-behaved class loaders maintain these properties:
Given the same name, a good class loader should always return the same class object.
If a class loader L1 delegates loading of a class C to another loader L2, then for any type T that occurs as the direct superclass or a direct superinterface of C, or as the type of a field in C, or as the type of a formal parameter of a method or constructor in C, or as a return type of a method in C, L1 and L2 should return the same Class object.
A malicious class loader could violate these properties. However, it could not undermine the security of the type system, because the Java Virtual Machine guards against this.
Mind the last sentence. A JVM will guard against violations of these requirements. With the repeated occurrences of the same symbolic references within your example code, there are two possibilities
The JVM remembers the result of the first resolution of this symbolic reference within this context and just reuses it on the next occurrence without asking a class loader again.
The JVM remembers the result of the first resolution of this symbolic reference within this context and compares it with the result of subsequent resolutions of the same reference and throws an error if they mismatch.
Since both approaches imply remembering the result, the first approach is usually used when it comes to resolving the same reference within the same context, as it is simpler and more efficient. When it comes to different symbolic references that resolve to classes using the same reference, the JVM will indeed throw an error when the class loader constraints are violated.
So expressions like Main.class == Main.class or new Main().getClass() == new Main().getClass() will never evaluate to false. Most likely, the resolution of the symbolic reference to Main will go a short-cut, using the same runtime class regardless of what the class loader would do. But even when it does not take the short-cut and the ClassLoader is misbehaving, returning a different class object for the next query, the JVM would detect it and throw an error, so the expression would not evaluate to a boolean result at all. In neither case could it result in false.
In a single classloader, the Class object is the same.
Is the class loader always 'well-behaved' and why (not)?
It really depends on the implementation. If it is done deliberately that always the classloader always returns a new Class-Object, it won't be well-behaved.
At least all classloaders of OpenJDK are well-behaving.
In other words: are Class instances singleton? The other way around: can a Class of the same type be a different instance?
In one single classloader, every Class instance is a singleton. With multiple classloaders, following will evaluate to false:
ClassLoaderA.getInstance().loadClass("foo.Bar")==ClassLoaderB.getInstance().loadClass("foo.Bar");
The other way around: can a Class of the same type be a different instance?
Only if loaded by two different, conforming,well-behaved classloaders.
As a side-step, but by no means the main question: because the singleton pattern's legitimate uses are point of debate, would Java's Class be a good candidate to apply the singleton pattern to?
This is quite opinion-based, but I think, it's no good candidate to apply the singleton pattern, as most singletons are implemented like this:
class Foo{
public static final Foo INSTANCE=new Foo();
private Foo(){
ìf(INSTANCE!=null)
throw new IllegalAccessException("No Foo instances for you!");
}
}
So more that it is really ONE object of a Class, many that only differ by some small things like a different Classloader.

Is it possible to define my own String class?

Is it possible to define my own String class which has the exact same name as java.lang.String? My assumption is that after I have defined it, I can use it directly or load it with a class loader.
Sorry, the code I wrote has a mistake. The String class of the parameter String[] args of the method main() was incorrectly referenced to my own defined String. That is why it occured a compile error.
My working result is that we can define a class named String in my own namespace or java.lang. But since JVM has loaded the default java.lang.String, we can't load our own String and use it.
Yes, you can define that class, but you won't be able to use it. The class java.lang.String will be loaded out of the JRE at bootstrap, and you can't reload a class in the bootstrap classloader. If you try to use your own classloader, the JVM will notice that java.lang.String is already loaded and just use that one.
From the JLS section on class loading:
Given the same name, a good class loader should always return the same class object. (This means that the java.lang.String class that gets pulled in a bootstrap will be the authoritative class.)
If a class loader L1 (the bootstrap loader) delegates loading of a class C to another loader L2 (your own loader), then for any type T (java.lang.String) that occurs as the direct superclass or a direct superinterface of C, or as the type of a field in C, or as the type of a formal parameter of a method or constructor in C, or as a return type of a method in C, L1 and L2 should return the same Class object. (Your own java.lang.String would be conflicting with all of the parameters and fields in anything else loaded by the bootstrap loader and would cause virtually anything past the loading of your rogue class to come crashing down with link or cast errors.)
What exactly are you trying to do, anyhow? java.lang.String has very strictly defined semantics, and changing its behavior at all would break an enormous amount of code.

How to create a JVM-global Singleton?

I was drawn inspiration from this stackoverflow question
How can one create a Java class instance that is guaranteed to be available only once for the entire JVM process? Every Application that runs on that JVM should then be able to use that singleton instance.
You can as a matter of fact implement such a singleton. The problem that was described to you in the comments is the possibility of a class being loaded by multiple ClassLoaders. Each of these ClassLoaders can then define a class of identical name which would erroneously assume to be unique.
You can however avoid this by implementing an accessor to your singleton which explicitly relies on checking a specific ClassLoader for a class of a given name which again contains your singleton. This way, you can avoid that a singleton instance is provided by two different ClassLoaders and such duplicating the instance you required to be unique throughout the JVM.
For reasons that are explained later, we will split up the Singleton and the SingletonAccessor into two different classes. For the following class, we need to later make sure that we always access it by using a specific ClassLoader:
package pkg;
class Singleton {
static volatile Singleton instance;
}
A convenient ClassLoader for this matter is the system class loader. The system class loader is aware of all classes on the JVM's class path and has per definition the extension and the bootstrap class loaders as its parents. Those two class loaders do not normally know about any classes that are domain-specific such as our Singleton class. This safes us from unwanted surprises. Furthermore, we know that it is accessible and known globally throughout a running instance of the JVM.
For now, let us assume that the Singleton class is on the class path. This way, we can receive the instance by this accessor using reflection:
class SingletonAccessor {
static Object get() {
Class<?> clazz = ClassLoader.getSystemClassLoader()
.findClass("pkg.Singleton");
Field field = clazz.getDeclaredField("instance");
synchronized (clazz) {
Object instance = field.get(null);
if(instance == null) {
instance = clazz.newInstance();
field.set(null, instance);
}
return instance;
}
}
}
By specifying that we explicitly want to load pkg.Singleton from the system class loader, we make sure that we always receive the same instance despite of which class loader loaded our SingletonAccessor. In the above example, we additionally make sure that Singleton is only instantiated once. Alternatively, you could put the instantiation logic into the Singleton class itself and make the unused instances rot in case other Singleton classes are ever loaded.
There is however a big drawback. You miss all means of type-safety as you cannot assume that your code is always run from a ClassLoader which delegates the class loading of Singleton to the system class loader. This is in particularly true for an application run on an application server which often implements child-first semantics for its class loaders and does not ask the system class loader for known types but first tries to load its own types. Note that a runtime type is characterized by two features:
Its fully-qualified name
Its ClassLoader
For this reason, the SingletonAccessor::get method needs to return Object instead of Singleton.
Another drawback is the fact that the Singleton type must be found on the class path for this to work. Otherwise, the system class loader does not know about this type. If you can put the Singleton type onto the class path, you are done here. No problems.
If you cannot make this happen, there is however another way by using for example my code generation library Byte Buddy. Using this library, we can simply define such a type at runtime and inject it into the system class loader:
new ByteBuddy()
.subclass(Object.class)
.name("pkg.Singleton")
.defineField("instance", Object.class, Ownership.STATIC)
.make()
.load(ClassLoader.getSytemClassLoader(),
ClassLoadingStrategy.Default.INJECTION)
You just defined a class pkg.Singleton for the system class loader and the above strategy is applicable again.
Also, you can avoid the type-safety issues by implementing a wrapper type. You can also automatize this with the help of Byte Buddy:
new ByteBuddy()
.subclass(Singleton.class)
.method(any())
.intercept(new Object() {
#RuntimeType
Object intercept(#Origin Method m,
#AllArguments Object[] args) throws Exception {
Object singleton = SingletonAccessor.get();
return singleton.getClass()
.getDeclaredMethod(m.getName(), m.getParameterTypes())
.invoke(singleton, args);
}
})
.make()
.load(Singleton.class.getClassLoader(),
ClassLoadingStrategy.Default.INJECTION)
.getLoaded()
.newInstance();
You just created a delegator which overrides all methods of the Singleton class and delegates their invocation to invocations of the JVM-global singleton instance. Note that we need to reload the reflective methods even though they are signature-identical because we cannot rely on the ClassLoaders of the delegate and the JVM-global classes to be the same.
In practice, you might want to cache the calls to SingletonAccessor.get() and maybe even the reflective method look-ups (which are rather expensive compared to the reflective method invocations). But this need depends highly on your application domain. If you have trouble with your constructor hierarchy, you could also factor out the method signatures into an interface and implement this interface for both the above accessor and your Singleton class.

Difference between MyClass.class and Class.forName("className")

We can get class Class object by 3 methods:
MyClass.class
obj.getClass
Class.forName("className")
I don't understood the difference between: MyClass.class and Class.forName("className").
Because both will need Class Name.
Class.forName("className");
forName is a static method of class "Class".
we require to provide the fully qualified name of the desired class.
this can be used when name of class will come to known at runtime.
ClassName.class;
.class is not a method it is a keyword and can be used with primitive type like int.
when Name of Class is known in advance & it is added to project, that time we use ClassName.class
I don't understood the difference between: MyClass.class and Class.forName("className").
Because both will need Class Name.
The big difference is when they need it. Since Class.forName accepts a string, the class name can be determined at runtime. Whereas of course, MyClass.class is determined at compile-time. This makes Class.forName useful for dynamically loading classes based on configuration (for instance, loading database drivers depending on the settings of a config file).
Rounding things out: obj.getClass() is useful because you may not know the actual class of an object — for instance, in a method where you accept an argument using an interface, rather than class, such as in foo(Map m). You don't know the class of m, just that it's something that implements Map. (And 99% of the time, you shouldn't care what its class is, but that 1% crops up occasionally.)
Class.forName("className");
It dynamically load the class based on fully qualified class name string.
obj.getClass
Returns the java.lang.Class object that represents the runtime class of the object.
MyClass.class:
A class literal is an expression consisting of the name of a class, interface, array,
or primitive type, or the pseudo-type void, followed by a'.' and the token class.
The type of C.class, where C is the name of a class, interface, or array type is Class<C>.
http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf
One important difference is:
A.class will perform loading and linking of class A.
Class.forName("A") will perform loading, linking and initialization of class A.

How to check whether a class is initialized?

You'll probably ask, why would I want to do that - it's because I'm using a class (from an external library) which does stuff in its static initializer and I need to know whether it's been done or not.
I looked at ClassLoader, but didn't find anything that looked useful. Any ideas?
You can use the ClassLoader.findLoadedClass() method. If it returns null, then the class isn't loaded. This way you don't load the class if it wasn't already loaded.
WARNING : This code doesn't really work here, in the system ClassLoader, findLoadedClass() is protected, you need to override it with your own ClassLoader.
Check the link below On the same topic to check if a class is loaded with the system ClassLoader
if(ClassLoader.getSystemClassLoader().findLoadedClass("java.lang.String") != null){
System.out.println("Yepee, String is loaded !");
}
Very good point from #irreputable :
"loaded" doesn't mean "initialized". initialization only happens at precise moments defined by JLS3 $12.4.1
And I quote :
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.
Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.
Resources :
Javadoc - ClassLoader.findLoadedClass()
Internals of Java Class Loading
JLS - §12.4.1 When Initialization Occurs
On the same topic :
In Java, is it possible to know whether a class has already been loaded?
Why don't you just reference the class (by creating a reference, creating an instance, or accessing a static member)? That will kick off the type initializer if it hasn't already fired and if it has then you are still good to go.
I know it is very late, but I think this answer might be useful. If you are not too scared (and you are allowed) to use the sun.misc.Unsafe class there is a method that precisely does that: The method
sun.misc.Unsafe.shouldBeInitialized(Class)
returns true if and only if the Class provided as parameter is (loaded but) not initialized.
You can try something like this:
Class c = new ClassLoader() { Class c = findLoadedClass(className); }.c;
You can get the JVM to print out classes as it loads them, using the -verbose flag. This might be of help to you.
java -verbose Dummy|head
[Opened C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.io.Serializable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Comparable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.CharSequence from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.String from C:\Program Files\Java\jre6\lib\rt.jar]
(btw, just tried this on a Hello World program and it loaded up 309 classes! wow)
Class.forName("com.abc.Xyz", true, this.getClass().getClassLoader())
It will block until the class has been initialized (by itself or some other thread)
If its not too late.. This should work fine as well
Class.forName().newInstance();
the newInstance() creates a new instance of the class represented by this Class object. The class is instantiated as if by a new expression with an empty argument list. The class is initialized if it has not already been initialized.

Categories

Resources