java.lang.ClassLoader:
It is the class responsible for finding and loading class files at run time. Creating your own ClassLoader lets you customize the JVM in useful and interesting ways, allowing you to completely redefine how class files are brought into the system.
Java program, unlike one written in C or C++, isn't a single executable file, but instead is composed of many individual class files, each of which corresponds to a single Java class.
Additionally, these class files are not loaded into memory all at once, but rather are loaded on demand, as needed by the program. The ClassLoader is the part of the JVM that loads classes into memory.
But it easy for the JVM to get classes from places other than the local hard drive or network. For example, browsers use a custom ClassLoader to load executable content from a Web site.
There are many other ways to get class files. Besides simply loading files from the local disk or from a network, you can use a custom ClassLoader to:
There are three categories of class loaders :
A common way to write a security-minded class loader is to use the following four steps:
Conclusion
The class loader architecture contributes to the JVM's security model in two ways:
Examples:
package com.kunal.testclassloader;
public class DefaultMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(java.lang.String.class.getClassLoader());//Prints null
System.out.println(ClassABC.class.getClassLoader());//Prints sun.misc.Launcher$AppClassLoader@4e0e2f2a
}
}
Loading Class Example :
Class to load :
package com.kunal.testclassloader;
public class ClassABC {
public void testGreet(){
System.out.println("From the loaded class");
}
}
Custom class Loader:
package com.kunal.testclassloader;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class MyClassLoadeer extends ClassLoader {
public MyClassLoadeer(){
super();
}
@Override
public Class<?> loadClass(String name)
throws ClassNotFoundException {
System.out.println("loading class '" + name + "'");
if (name.startsWith("com.kunal.")) {
try {
return getClass(name);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return super.loadClass(name);
}
private Class<?> getClass(String name) throws ClassNotFoundException, IOException {
// We are getting a name that looks like
// javablogging.package.ClassToLoad
// and we have to convert it into the .class file name
// like javablogging/package/ClassToLoad.class
String file = name.replace('.', File.separatorChar)
+ ".class";
byte[] b = null;
// This loads the byte code data from the file
b = loadClassData(file);
// defineClass is inherited from the ClassLoader class
// and converts the byte array into a Class
Class<?> c = defineClass(name, b, 0, b.length);
resolveClass(c);
return c;
}
private byte[] loadClassData(String file) throws IOException {
// Opening the file
InputStream stream = getClass().getClassLoader()
.getResourceAsStream(file);
int size = stream.available();
byte buff[] = new byte[size];
DataInputStream in = new DataInputStream(stream);
// Reading the binary data
in.readFully(buff);
in.close();
return buff;
}
}
Main Class named DefaultMain:
package com.kunal.testclassloader;
import java.lang.reflect.InvocationTargetException;
public class DefaultMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(java.lang.String.class.getClassLoader());//Prints null
System.out.println(ClassABC.class.getClassLoader());//Prints sun.misc.Launcher$AppClassLoader@4e0e2f2a
MyClassLoadeer loader = new MyClassLoadeer();
try {
Class<?> classLoaded = loader.loadClass("com.kunal.testclassloader.ClassABC");
try {
Object abc = classLoaded.newInstance();
System.out.println(abc.getClass().getClassLoader());
// ((ClassABC)abc).testGreet();
try {
classLoaded.getMethod("testGreet", null).invoke(abc, null);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Output:
null
sun.misc.Launcher$AppClassLoader@4e0e2f2a
loading class 'com.kunal.testclassloader.ClassABC'
loading class 'java.lang.Object'
com.kunal.testclassloader.MyClassLoadeer@6d06d69c
loading class 'java.lang.System'
loading class 'java.io.PrintStream'
From the loaded class
Comments for improvement are welcome.
It is the class responsible for finding and loading class files at run time. Creating your own ClassLoader lets you customize the JVM in useful and interesting ways, allowing you to completely redefine how class files are brought into the system.
Java program, unlike one written in C or C++, isn't a single executable file, but instead is composed of many individual class files, each of which corresponds to a single Java class.
Additionally, these class files are not loaded into memory all at once, but rather are loaded on demand, as needed by the program. The ClassLoader is the part of the JVM that loads classes into memory.
Why write a ClassLoader?
If the JVM has a ClassLoader, then why would you want to write another one? The default ClassLoader only knows how to load class files from the local filesystem. This is fine for regular situations, when you have your Java program fully compiled and waiting on your computer.But it easy for the JVM to get classes from places other than the local hard drive or network. For example, browsers use a custom ClassLoader to load executable content from a Web site.
There are many other ways to get class files. Besides simply loading files from the local disk or from a network, you can use a custom ClassLoader to:
- Automatically verify a digital signature before executing untrusted code
- Transparently decrypt code with a user-supplied password
- Create dynamically built classes customized to the user's specific needs
There are three categories of class loaders :
- BootStrap of Premodial class loaders : Deals with rt.jar or primitive classes that java offers.
- Extension Class loaders:
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.dirsproperty. TheExtClassLoaderis responsible for loading all .jar files kept in thejava.ext.dirspath. 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.
- Application class loaders:
The third and most important class loader from the developer perspective is theAppClassLoader. The application class loader is responsible for loading all of the classes kept in the path corresponding to thejava.class.pathsystem property.
A java classloader works on chiefly three principle: delegation,visibility and uniqueness.
Delegation principlesAs discussed on when a class is loaded and initialized in Java, a class is loaded in Java, when its needed. Suppose you have an application specific class called Abc.class, first request of loading this class will come to Application ClassLoader which will delegate to its parent Extension ClassLoader which further delegates to Primordial or Bootstrap class loader. Primordial will look for that class in rt.jar and since that class is not there, request comes to Extension class loader which looks on jre/lib/ext directory and tries to locate this class there, if class is found there than Extension class loader will load that class and Application class loader will never load that class but if its not loaded by extension class-loader than Application class loader loads it from Classpath in Java. Remember Classpath is used to load class files while PATH is used to locate executable like javac or java command.Visibility PrincipleAccording to visibility principle, Child ClassLoader can see class loaded by Parent ClassLoader but vice-versa is not true. Which mean if class Abc is loaded by Application class loader than trying to load class ABC explicitly using extension ClassLoader will throw either java.lang.ClassNotFoundException. as shown in below Example
A common way to write a security-minded class loader is to use the following four steps:
- If packages exist that this class loader is not allowed to load from, the class loader checks whether the requested class is in one of those forbidden packages mentioned above. If so, it throws a security exception. If not, it continues on to step two.
- The class loader passes the request to the primordial class loader. If the primordial class loader successfully returns the class, the class loader returns that same class. Otherwise it continues on to step three.
- If trusted packages exist that this class loader is not allowed to add classes to, the class loader checks whether the requested class is in one of those restricted packages. If so, it throws a security exception. If not, it continues on to step four.
- Finally, the class loader attempts to load the class in the custom way, such as by downloading it across a network. If successful, it returns the class. If unsuccessful, it throws a "no class definition found" error.
Conclusion
The class loader architecture contributes to the JVM's security model in two ways:
- by separating code into multiple name-spaces and placing a "shield" between code in different name-spaces
- by guarding the borders of trusted class libraries, such as the Java API
Examples:
package com.kunal.testclassloader;
public class DefaultMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(java.lang.String.class.getClassLoader());//Prints null
System.out.println(ClassABC.class.getClassLoader());//Prints sun.misc.Launcher$AppClassLoader@4e0e2f2a
}
}
Loading Class Example :
Class to load :
package com.kunal.testclassloader;
public class ClassABC {
public void testGreet(){
System.out.println("From the loaded class");
}
}
Custom class Loader:
package com.kunal.testclassloader;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class MyClassLoadeer extends ClassLoader {
public MyClassLoadeer(){
super();
}
@Override
public Class<?> loadClass(String name)
throws ClassNotFoundException {
System.out.println("loading class '" + name + "'");
if (name.startsWith("com.kunal.")) {
try {
return getClass(name);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return super.loadClass(name);
}
private Class<?> getClass(String name) throws ClassNotFoundException, IOException {
// We are getting a name that looks like
// javablogging.package.ClassToLoad
// and we have to convert it into the .class file name
// like javablogging/package/ClassToLoad.class
String file = name.replace('.', File.separatorChar)
+ ".class";
byte[] b = null;
// This loads the byte code data from the file
b = loadClassData(file);
// defineClass is inherited from the ClassLoader class
// and converts the byte array into a Class
Class<?> c = defineClass(name, b, 0, b.length);
resolveClass(c);
return c;
}
private byte[] loadClassData(String file) throws IOException {
// Opening the file
InputStream stream = getClass().getClassLoader()
.getResourceAsStream(file);
int size = stream.available();
byte buff[] = new byte[size];
DataInputStream in = new DataInputStream(stream);
// Reading the binary data
in.readFully(buff);
in.close();
return buff;
}
}
Main Class named DefaultMain:
package com.kunal.testclassloader;
import java.lang.reflect.InvocationTargetException;
public class DefaultMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(java.lang.String.class.getClassLoader());//Prints null
System.out.println(ClassABC.class.getClassLoader());//Prints sun.misc.Launcher$AppClassLoader@4e0e2f2a
MyClassLoadeer loader = new MyClassLoadeer();
try {
Class<?> classLoaded = loader.loadClass("com.kunal.testclassloader.ClassABC");
try {
Object abc = classLoaded.newInstance();
System.out.println(abc.getClass().getClassLoader());
// ((ClassABC)abc).testGreet();
try {
classLoaded.getMethod("testGreet", null).invoke(abc, null);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Output:
null
sun.misc.Launcher$AppClassLoader@4e0e2f2a
loading class 'com.kunal.testclassloader.ClassABC'
loading class 'java.lang.Object'
com.kunal.testclassloader.MyClassLoadeer@6d06d69c
loading class 'java.lang.System'
loading class 'java.io.PrintStream'
From the loaded class
Comments for improvement are welcome.
No comments:
Post a Comment