作用
- 将Class加载到JVM
- 审查类由谁加载
- 字节码解析成JVM统一要求的对象格式
类结构分析
常用方法:
findClass(String) Class<?>;
loadClass(String) Class<?>;
resolveClass(Class<?>) void;
defineClass(byte[],int,int)
调用JNI把class字节码转化为实例
findClass(String)
由具体的子类实现,通过本地,或者net等方式查找byte文件,并调用defineClass方法来返回实例
示例:
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getData(name);//具体获取字节码的方法,可以通过io读取
if (classData == null){
throw new ClassNotFoundException();
}else {
return defineClass(className, classData, 0, classData.length);
}
}
loadClass(String , boolean)
源码如下:
1、findLoadClass(name);判断是否已经加载,未加载执行2;
2、父类加载器存在,使用父类加载器尝试加载( c = parent.loadClass(name, false);),不存在使用内置加载器(c = findBootstrapClassOrNull(name);)
3、如果仍未加载,调用findClass(String)方法加载;
4、根据第二个参数,来决定是否resolveClass(Class<?>)(连接);
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
resolveClass(Class<?>)
链接Class,调用JNI。
综上:
当定义自己的类加载器时,重写findClass()方法,调用defineClass()方法即可。如上面示例所示