JVM(Java Virtual Machine) ilk
çalışırken sınıfların yüklenmesinden sorumlu Class tır diyebiliriz. Java da
Interpretation(yorumlama) işleminden önce Class Loading işlemleri gerçekleşir.
Her Class uniq olarak ClassLoader tarafından JVM Memory e yüklenir. JVM Class
Loading işlemlerini yaparken, yani bir java uygulamasını ilk olarak ayağa
kaldırırken, daha uygulamamız hiç çalışmaya başlamadan önce, ClassLoader sınıfından
extend ederek sınıf yükleme işlemlerini özelleştirmemize olanak sağlar. Örneğin
aynı isimli sınıfı iki kez özel olarak load edebiliriz, yada uygulama açılmadan
önce güvenlik amaçlı kontroller yada şifrelemeler yapabiliriz.
Class
Loading işlemi: JVM de önce Bootstrap Class Loader ile, java.lang, java.util vb
gibi paketler içindeki çekirdek classlar yüklenir. Sonra kullanıcı tanımlı
Class Loader lar çalışır. Sonra Array Classları create edilir, Constraint ler
load edilir, türetilmiş classlara geçilir.
JVM,
Class loading işleminden sonra; Classların doğrulanarak hazırlanıp,
çözümlenmesi - Linking(Verification,Preparation,Resolution) sonra da yüklenen
ve bağlanan Classların başlatılması - Initialization işlemlerini
gerçekleştirir. Buraya kadar sorun yoksa normal şartlarda uygulama ayağa
kalkmış demektir.
Hiyerarşik
olarak Java Class Loader lar;
1)Bootstrap
Class Loader : Bu java runtime ortamının parçası olan sınıflardır, “JAVA_HOME/jre/lib/rt.jar”
içinde bulunan java.util, java.lang vb. gibi java çekirdek sınıflarını yükler.
Bootstrap sınıf yükleyicisi native implementation dur ve bu yüzden farklı
JVM'lerde farklılık gösterebilir.
2) Extensions
Class Loader : “JAVA_HOME/jre/lib/ext” altındaki sınıfları yükler.
3) System
Class Loader : Java classpath de belirtilmiş olan sınıfları yükler.
Şekil
:
Java SE 7 JVM mimarisinde, JVM spesifikasyonu.
Örnek
Özelleştirilmiş ClassLoader:
package classloaders.ocp7;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
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 {
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);
}
Class<?> c = defineClass(name, classData, 0, classData.length);
resolveClass(c);
classes.put(name, c);
return c;
}
/**
* Load the class file into byte array
*/
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
*/
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("classloaders.ocp7.TestClass");
Object o = c.newInstance();
Method m = c.getMethod("toString");
System.out.println(m.invoke(o));
}
}
Test sınıfı:
package classloaders.ocp7;
public class TestClass {
public String toString() {
String
aciklama = "Bu bir test
sınıfıdır.";
return aciklama;
}
}
Kaynaklar: