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.
Related
From the JLS (§15.8.2):
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.
This makes sense, but what if there is no 'current instance'? (i.e. the expression is in a class method, aka 'static method')
My intuition tells me to use the same rule, swapping out 'class of the current instance' for something like 'class of the class method'. However, I cannot find any such rule in the JLS, which in my experience tends to be very explicit. This makes me uncertain about my intuition.
The alternative is that my assumption that there is no 'current instance' when in a class method, is incorrect. If so - what are the rules for determining the 'current instance' when in a class method?
Class of the current instance indicates the instance of java.lang.Class whose type is T. Even if the class in consideration has static method, It is always an instance of java.lang.Class.
You can get related explanation in Java Documentation for java.lang.Class:
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.
The following example uses a Class object to print the class name of an object:
void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
}
It is also possible to get the Class object for a named type (or for void) using a class literal. See Section 15.8.2 of The Java™ Language Specification. For example:
System.out.println("The name of class Foo is: "+Foo.class.getName());
I believe "instance" in this case refers to the instance of the class itself, i.e., the class definition, and not an object instance of that class. This is difficult to articulate, so let's consider an example:
class A {}
class B {
Class<A> a = A.class;
}
Here, the expression A.class executes within a class B. However, it is possible that class B might be loaded into the runtime more than once using different class loaders. So, when the documentation says, "as defined by the defining class loader (§12.2) of the class of the current instance", I believe it is referring to whichever class loader loaded the copy ("instance") of the B class that is currently executing.
In short, the Class<A> instance assigned to a will be loaded from the same class loader that loaded B.
In practice, this isn't the sort of thing you're likely to have to have to worry about. Most Java developers don't have to deal with multiple class loaders in their day-to-day work.
The class literal can never appear alone, it must always be qualified by either a class name or a primitive type name. class should be used when you need to access a class object statically. someObject.getClass() should be used when you need to access an objects class at runtime.
Thus:
public class Foo {
public static String getMyFooClassNameStatic_good() {
return Foo.class.getName(); // ok
}
public static String getBarClassName() {
// the Bar class will be looked up in the same class loader as
// the one that the the Foo CLASS instance was loaded from that
// is executing this method. So if there are multiple versions
// of Bar floating around, the one you will get is the one that
// was loaded from the same class loader as the loaded Foo. That's
// what the language about "current instance" in the spec is
// getting at.
return Bar.class.getName();
}
public static String getMyFooClassNameStatic_bad() {
return class.getName(); // syntax error -
// use one of:
// Foo.class.getName()
// (new Foo()).getClass().getName()
// Class.forName("Foo").getName()
}
public static String getIntClassName() {
return int.class.getName(); // ok
}
}
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.
If one needs to use a Class<T> as part of a key of a Map what is the proper way to define the hashCode and equals?
A Class<T> inherits the ones from Object which check for reference equality and return the memory address as the hashcode but in my mind it is not clear what is the meaningful definition of equals and hashCode definition of a Class<T>.
Should I use theClass.getClass().hashCode(); for example (where we have Class<T> theClass;) to use the actual instance's methods?
But this does not seem to be the correct thing to do.
For example in the javadoc for Class<T>:
Every array also belongs to a class that is reflected as a Class
object that is shared by all arrays with the same element type and
number of dimensions
So it seems in some cases the same Class<T> is shared among objects? So what would be the way to follow? Perhaps use theClass.hashCode() and theClass.equals() to use reference equality? Not sure at all here.
The implementation of hashCode and equals java.lang.Class inherits from java.lang.Object is meaningful and usually appropriate, as all instances of a class are guaranteed to return the same Class object from getClass(), i.e.
new Integer(2).getClass() == new Integer(3).getClass();
This is somewhat buried in the docs; the javadoc of getClass() writes:
Returns:
The Class object that represents the runtime class of this object.
See Also:
Literals, section 15.8.2 of The Java™ Language Specification.
That section writes:
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.
and section 12.2 writes:
Well-behaved class loaders maintain these properties:
Given the same name, a good class loader should always 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.
And yes, if the same class definition is loaded by different class loaders, the class objects will not be equal. As the runtime treats these as independent classes (who just happen to share the same name, but need not otherwise be similar, let alone binary compatible), this is usually desired.
The method String getName() returns a unique String representation of the Class. You can use this String for equals/hashCode as an ordinary String if your program does not use more than one classloader.
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.
Imagine a Java class which has most features that you can find in a class. For example: it inherits from another class, implements a couple of interfaces, includes some 'static final' constants, some final constants, some static variables, instance variables, a static block, an unnamed code block (just code in {}), constructors, methods etc.
When the class in question is loaded into the JVM for the first time, in what order are the various portions of the class initialized or loaded into the JVM? What does the call stack in the JVM look like for the loading? Assume that only one classloader is at work here.
This is going back to the absolute basics/internals of Java, but I havent been able to find a good article explaining the correct sequence.
This could be described in the section 2.17.4 of the JVMS 5.0/6
2.17.4 Initialization
Initialization of a class consists of:
executing its static initializers (§2.11) and
the initializers for static fields (§2.9.2) declared in the class.
Initialization of an interface consists of executing the initializers for fields declared in the interface (§2.13.3.1).
Before a class or interface is initialized, its direct superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized.
A class or interface type T will be initialized immediately before one of the following occurs:
T is a class and an instance of T is created.
T is a class and a static method of T is invoked.
A nonconstant static field of T is used or assigned. A constant field is one that is (explicitly or implicitly) both final and static, and that is initialized with the value of a compile-time constant expression. A reference to such a field must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.
Invocation of certain methods in library classes (§3.12) also causes class or interface initialization. See the Java 2 platform's class library specifications (for example, class Class and package java.lang.reflect) for details.
The intent here is that a type have a set of initializers that put it in a consistent state and that this state be the first state that is observed by other classes. The static initializers and class variable initializers are executed in textual order and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope. This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.
Before a class or interface is initialized its superclass is initialized, if it has not previously been initialized.
The updated version of Initialization in JVMS 8 is in Chapter 5.5
Initialization of a class or interface consists of executing its class or interface initialization method (§2.9).
A class or interface may be initialized only as a result of:
The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references the class or interface (§new, §getstatic, §putstatic, §invokestatic).
All of these instructions reference a class directly or indirectly through either a field reference or a method reference.
Upon execution of a new instruction, the referenced class or interface is initialized if it has not been initialized already.
Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.
The first invocation of a java.lang.invoke.MethodHandle instance which was the result of resolution of a method handle by the Java Virtual Machine (§5.4.3.5) and which has a kind of 2 (REF_getStatic), 4 (REF_putStatic), 6 (REF_invokeStatic), or 8 (REF_newInvokeSpecial).
Invocation of certain reflective methods in the class library (§2.12), for example, in class Class or in package java.lang.reflect.
The initialization of one of its subclasses.
Its designation as the initial class at Java Virtual Machine start-up (§5.2).
Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.
Because the Java Virtual Machine is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time.
There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface.
The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure.
It assumes that the Class object has already been verified and prepared, and that the Class object contains state that indicates one of four situations:
This Class object is verified and prepared but not initialized.
This Class object is being initialized by some particular thread.
This Class object is fully initialized and ready for use.
This Class object is in an erroneous state, perhaps because initialization was attempted and failed.
How about the JLS, specifically section 12.4?