In org.springframework.core.SerializableTypeWrapper (version 5.2.3), there is the following code at line 112:
if (GraalDetector.inImageCode() || !Serializable.class.isAssignableFrom(Class.class)) {
// Let's skip any wrapping attempts if types are generally not serializable in
// the current runtime environment (even java.lang.Class itself, e.g. on Graal)
return providedType;
}
I'm curious about the second check (!Serializable.class.isAssignableFrom(Class.class)): is it possible for it to evaluate to true (that is, for Serialazable.class to be not assignable from Class.class)?
Here is what Class#isAssignableFrom() javadoc says:
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.
Looking at the code of Class, I see the following:
public final class Class<T> implements java.io.Serializable
So Serializable is a superinterface of Class and should always be assignable from Class. But the check in the Spring code suggests that sometimes it's not.
How come? In what situations can this happen and why don't they violate the Java Language Specification?
A custom class loader is a possible (if unlikely) mechanism for the expression to return false. Custom class loaders can do some crazy things, including loading their own versions of standard Java classes. Some things to know about class loaders:
Custom class loaders can be configured to load any class, even including Java standard library classes (it's discouraged of course, but still possible)
Custom class loaders will typically be configured to delegate to the system class loader for classes that they don't know how to load.
When class A has a reference to class B, the reference will be resolved using whichever class loader was used to load class A
More than one class loader can be configured to handle the same class, which can lead to multiple versions of a class getting loaded into the JVM, with the actual implementation you get depending on which class loader you ask
Suppose there is a custom class loader that, for whatever reason, is configured to load java.io.Serializable by itself, but delegates to the system class loader for loading other classes, including java.lang.Class.
Now suppose this custom class loader is used to load SerializableTypeWrapper. This means it will also be used to resolve the reference to java.io.Serializable in SerializableTypeWrapper. With the reference to java.lang.Class, the custom class loader will delegate this to the system class loader. The system class loader will be used to load java.lang.Class, but it will also be used to load the reference to java.io.Serializable from within java.lang.Class.
So now we can ask the question - is java.io.Serializable [custom] assignable from java.lang.Class [standard]? And the answer is no - java.lang.Class does implement java.io.Serializable [standard], but it does not implement java.io.Serializable [custom].
Related
I was studying the Java architecture and in between, I found a concept of class loader and it was also referenced as a primordial class loader. I want to know that what is the function of this class loader, why we use this? I also want to know that what was the basic need so that we are using this.
In Java every class has to be loaded by some class loader.
How is the first class loaded? It has to be loaded through some class loader (which is just another class), so without some special code this would lead to infinity recursion.
The class loader that loads the first classes (java.lang.Object, java.lang.Class, java.lang.String, java.lang.ClassLoader and others) can therefore not be a 'normal' class loader.
It is this class loader that is referenced as the primordial class loader (primordial: from latin, meaning "the first", "the origin(al)")
For further study see the Java Security Aritecture and Securing Java
Primordial class loader the first class loader responsible to load class loader like "BootStrap class loader" which is part of JVM and written in native language.
Oracle JavaDocs explains that IllegalAccessError is
"Thrown if an application attempts to access or modify a field, or to
call a method that it does not have access to."
I try to load a class dynamically and I get this exception.
if I understand correctly when you use a classloader to load a class with a private package dynamically IllegalAccessError happens
the class I am trying to load is using
org.xml.sax.helpers.SecuritySupport
which also states in their description in the following url
http://grepcode.com/file/repository.springsource.com/org.apache.xmlcommons/com.springsource.org.apache.xmlcommons/1.3.4/org/xml/sax/helpers/SecuritySupport.java
that
Unfortunately, we can't load the class using reflection
* because the class is package private. And the class has
* to be package private so the APIs aren't exposed to other
* code that could use them to circumvent security. Thus,
* we accept the risk that the direct reference might fail
* on some JDK 1.1 JVMs, even though we would never execute
* this code in such a case. Sigh...
how can I dynamically load it anyway? I have to get it to work.
also if I get an error when I use a classloader, I cannot recover from that, so how can I know in advance that I cannot load this class?
thanks in advance to anyone who helps
The statement “we can't load the class using reflection because the class is package private” doesn’t make any sense, as can be shown easily:
package somepackage;
class BaseClass {
public static void main(String[] args) throws ReflectiveOperationException {
BaseClass obj=(BaseClass)
Class.forName("somepackage.SubClass").newInstance();
obj.aMethod();
}
void aMethod() {
System.out.println("base class");
}
}
class SubClass extends BaseClass {
#Override
void aMethod() {
System.out.println("method overridden by subclass");
}
}
This works flawlessly, printing method overridden by subclass replicated the actual use case of that SecuritySupport class.
However, since that class obviously serves the purpose of allowing a transition between Java 1.1 and Java 1.2, it might be possible that there were such restrictions twenty years ago, when this transition happened.
Your use case, however, is entirely different. You say that you are trying to load a class which “is using org.xml.sax.helpers.SecuritySupport”, which doesn’t imply that it is using said class via Reflection, but as shown above, that doesn’t matter anyway. It either case, it would only work, if the class is in the same package, whether you load the class “dynamically” or not.
There are only two possible scenarios.
If the class is truly within the same package, which at runtime implies that it also has been loaded by the same class loader, which would require that is also part of the JRE, if the JRE’s org.xml.sax.helpers package defines a SecuritySupport class, then the class can access the class within the same package.
If you are trying to load a class via a different ClassLoader from a different code source, it will not be of that package, even if you’d give it a qualified name of the org.xml.sax.helpers.SomeClass form. If the JRE’s org.xml.sax.helpers package happens to define a SecuritySupport class, all non-JRE classes would be in a different package. When it tries to access that class, which is not part of the official API, it doesn’t work.
Note that all standard class loaders follow a delegation model trying to resolve a name through their parent class loader first, which is the reason why they all would prefer the JRE’s org.xml.sax.helpers.SecuritySupport class, if there is one. With non-standard class loaders, you could have different, unrelated classes with that qualified name, being in different runtime packages.
In that second scenario, the question arises, why your class is using that class. In 2017, there’s rarely a need to differentiate between Java 1.1 and Java 1.2 and the functionality offered by that class is also only relevant for a class within the privileged code source of the JRE (or different code sources with different privileges in general).
From this question, I found that it is not possible to look up a class from a sun.misc.DelegatingClassLoader, i.e. looking up a class on its own class loader like
Class<?> accessor = ...
accessor.getClassLoader().findClass(accessor.getName());
throws a ClassNotFoundException. The delegating class loader is used for loading runtime-generated accessor classes for converting Java's reflective JNI calls into Java invocations.
For some strange reason, I am not able to find the source of the DelegatingClassLoader anywhere in the JDK sources even though it is clearly available in my build where it seems to be an empty implementation of a subclass of the standard ClassLoader from looking at the class's byte code.
If the DelegatingClassLoader is however really only a simple subclass, I do not understand why it is not possible to look up a class by its name. Is there some VM magic involved? It seems like the
private native final Class<?> findLoadedClass0(String name);
method does not return the loaded class for a DelegatingClassLoader. The private classes field does however include the loaded class.
I was not able to find any information on how these class loaders are supposed to be different from any other class loaders. I am looking for an explanation why the above lookup does not work but throws an exception.
The source for DelegatingClassLoader is for whatever reason located in ClassDefiner.java. Interestingly, this code has a comment that references bug 4474172, which suggests that this class loader is known to the JVM and has special behavior:
The second solution is to make the virtual machine "magically"
delegate class loading for these newly-fabricated class loaders to
their parent loaders, without making an upcall to Java. The
disadvantage is that this is another hack in the JVM [...]. This
option has been chosen.
Assume I obtained a Class object by loading a class dynamically using Class.forName("Foo"). Foo is abstract in this case, so I cannot call newInstance() on it. (How) is it possible to declare a concrete subclass of Foo?
You declare it as not abstract e.g.
class Bar extends Foo {
// implement methods are required.
}
In short, just because you loaded the class dynamically doesn't mean the rules change ;)
Foo is not available at compile-time
If you don't have Foo available at compile time, you still need to have a sub-class of this class which is concrete to create it. To do this you have two options.
find a concrete class and create that. You can use the Reflections library to find such a class.
generate code and compile it using the Compiler API, or BeanShell.
generate byte code for the subclass using ObjectWeb's ASM.
I suspect the first option is what you need because unless there is a subclass provided for you, you still need to generate the code for the abstract methods.
Why is it advisable to load the Java Runtime classes and API classes using the default system class loader in Java? What happens if we load them using our custom class loader?
One of the criterias for instanceof to be true, is that the two classes must be loaded by the same classloader. This goes for class casting too.
This would mean that instances of e.g. String created by your class loader would not be compatible with the String created by the system class loader. Are not instances of and cannot be cast to.
You probably do not want that.