ClassLoader功能
类的加载
JVM运行的时候,当用到一个类的时候,需要把类字节码文件加载到内存并生成运行时数据结构,其中classLoader的角色必不可少
classLoader加载一个类的时候,会调用其如下方法
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
双新委派机制
其中调用的方法
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{
...
Class<?> c = findLoadedClass(name);
if (c == null) {
...
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
...
if (c == null) {
...
c = findClass(name);
...
}
}
...
return c;
}
就是classLoader的双新委派机制,它是可以被子类重写的,当自定义的classLoader的重写这个方法可以打破双新委派的机制
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
此方法需要具体的classLoader来实现
字节码与类的注册
findClass的实现里面经常会用到如下方法
protected final Class<?> defineClass(String name, byte[] b, int off, int len)throws ClassFormatError{
return defineClass(name, b, off, len, null);
}
protected final Class<?> defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)throws ClassFormatError{
protectionDomain = preDefineClass(name, protectionDomain);
String source = defineClassSourceLocation(protectionDomain);
Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}
private native Class<?> defineClass1(String name, byte[] b, int off, int len, ProtectionDomain pd, String source);
最终是通过native的defineClass1来实现字节码加载到内存结构中去的
资源加载
程序中还经常使用classLoader来获取资源
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
}
if (url == null) {
url = findResource(name);
}
return url;
}
protected URL findResource(String name) {
return null;
}
就是通过把资源名转换成URL的方式来实现的