What is a ClassLoader?
Importing the compiled class into the JVM to execute
Among commercially popular programming languages, the Java language distinguishes itself
by running on a Java virtual machine (JVM). This means that compiled programs are
expressed in a special, platform-independent format, rather than in the format of the
machine they are running on. This format differs from traditional executable program formats
in a number of important ways.
In particular, a 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.
The Java ClassLoader, furthermore, is written in the Java language itself. This means that it's
easy to create your own ClassLoader without having to understand the finer details of the
JVM.
Below is the example for custom class loading
package com.javasoul.classloader;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
*
* Simple custom class loader implementation
*
*/
public class CustomClassLoader extends ClassLoader {
/**
* The HashMap where the classes will be cached
*/
private Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
@Override
public String toString() {
return CustomClassLoader.class.getName();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
/**Searches through cache of Class Instances If it founds retruns the Class Instance
*
*/
if (classes.containsKey(name)) {
return classes.get(name);
}
byte[] classData;
try {
classData = loadClassData(name);
} catch (IOException e) {
throw new ClassNotFoundException("Class [" + name
+ "] could not be found", e);
}
/**
* byte [] of the physical class file is passed to the defineClass method
*/
Class<?> c = defineClass(name, classData, 0, classData.length);
resolveClass(c);
/**
* Putting inside the cache for reuse
*/
classes.put(name, c);
return c;
}
/**
* Load the class file into byte array
*
* @param name
* The name of the class e.g. com.codeslices.test.TestClass}
* @return The class file as byte array
* @throws IOException
*/
private byte[] loadClassData(String name) throws IOException {
BufferedInputStream in = new BufferedInputStream(ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ ".class"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
in.close();
byte[] classData = out.toByteArray();
out.close();
return classData;
}
/**
* Simple usage of the CustomClassLoader implementation
*
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException,
InvocationTargetException
{
CustomClassLoader loader = new CustomClassLoader();
// This class should be in your application class path
Class<?> c = loader.findClass("com.javasoul.Blog");
/**
* Invoking the constructor with arg-types and instantiating the object with arg-list
*/
Constructor constr = c.getConstructor(Long.TYPE,String.class,String.class,Long.TYPE);
Object o = constr.newInstance(1,"Java Souls","rafi",System.currentTimeMillis());
Method m = c.getMethod("toString");
System.out.println(m.invoke(o));
}
}
Blog.java
package com.javasoul;
public class Blog {
private long bloggerId;
private String bloggerName;
private String author;
private long creationtime;
public Blog(long bloggerId, String bloggerName, String author, long creationtime){
this.bloggerId = bloggerId;
this.bloggerName = bloggerName;
this.author = author;
this.creationtime = creationtime;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Blog Id : "+bloggerId);
sb.append("\tBlogger Name : "+bloggerName);
sb.append("\tAuthor of Blog : "+author);
sb.append("\tcreation time : "+creationtime);
return sb.toString();
}
}
Importing the compiled class into the JVM to execute
Among commercially popular programming languages, the Java language distinguishes itself
by running on a Java virtual machine (JVM). This means that compiled programs are
expressed in a special, platform-independent format, rather than in the format of the
machine they are running on. This format differs from traditional executable program formats
in a number of important ways.
In particular, a 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.
The Java ClassLoader, furthermore, is written in the Java language itself. This means that it's
easy to create your own ClassLoader without having to understand the finer details of the
JVM.
Below is the example for custom class loading
package com.javasoul.classloader;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
*
* Simple custom class loader implementation
*
*/
public class CustomClassLoader extends ClassLoader {
/**
* The HashMap where the classes will be cached
*/
private Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
@Override
public String toString() {
return CustomClassLoader.class.getName();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
/**Searches through cache of Class Instances If it founds retruns the Class Instance
*
*/
if (classes.containsKey(name)) {
return classes.get(name);
}
byte[] classData;
try {
classData = loadClassData(name);
} catch (IOException e) {
throw new ClassNotFoundException("Class [" + name
+ "] could not be found", e);
}
/**
* byte [] of the physical class file is passed to the defineClass method
*/
Class<?> c = defineClass(name, classData, 0, classData.length);
resolveClass(c);
/**
* Putting inside the cache for reuse
*/
classes.put(name, c);
return c;
}
/**
* Load the class file into byte array
*
* @param name
* The name of the class e.g. com.codeslices.test.TestClass}
* @return The class file as byte array
* @throws IOException
*/
private byte[] loadClassData(String name) throws IOException {
BufferedInputStream in = new BufferedInputStream(ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ ".class"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
in.close();
byte[] classData = out.toByteArray();
out.close();
return classData;
}
/**
* Simple usage of the CustomClassLoader implementation
*
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException,
InvocationTargetException
{
CustomClassLoader loader = new CustomClassLoader();
// This class should be in your application class path
Class<?> c = loader.findClass("com.javasoul.Blog");
/**
* Invoking the constructor with arg-types and instantiating the object with arg-list
*/
Constructor constr = c.getConstructor(Long.TYPE,String.class,String.class,Long.TYPE);
Object o = constr.newInstance(1,"Java Souls","rafi",System.currentTimeMillis());
Method m = c.getMethod("toString");
System.out.println(m.invoke(o));
}
}
Blog.java
package com.javasoul;
public class Blog {
private long bloggerId;
private String bloggerName;
private String author;
private long creationtime;
public Blog(long bloggerId, String bloggerName, String author, long creationtime){
this.bloggerId = bloggerId;
this.bloggerName = bloggerName;
this.author = author;
this.creationtime = creationtime;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Blog Id : "+bloggerId);
sb.append("\tBlogger Name : "+bloggerName);
sb.append("\tAuthor of Blog : "+author);
sb.append("\tcreation time : "+creationtime);
return sb.toString();
}
}
No comments:
Post a Comment