动态类加载
代码块加载顺序
这里的代码块主要指的是这四种
静态代码块:static{}
构造代码块:{}
无参构造器:ClassName()
有参构造器:ClassName(String name)
我创建两个类
Person.java
public class Person {
public static int staticVar;
public static int id;
static {
System.out.println("静态代码块");
}
{
System.out.println("构造代码块");
}
Person(){
System.out.println("无参构造器");
}
Person(int id){
System.out.println("有参构造器");
}
public static void staticAction(){
System.out.println("静态方法");
}
}
Main.java
public class Main {
public static void main(String[] args) {
new Person();
}
}
他会输出
静态代码块
构造代码块
无参构造器
Person.staticAction();
他会输出
静态代码块
静态方法
Person.id = 1;
他会输出
静态代码块
ok上面的看完了,我们就来获取这个类
Class c = Person.class;
他啥也不输出,所以他没有进行初始化
Class.forName("org.example.Person");
他会输出
静态代码块
说明进行了初始化的操作,我们跟进这个函数
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
进入forName0
private static native Class<?> forName0(String name, boolean initialize,
ClassLoader loader,
Class<?> caller)
throws ClassNotFoundException;
他第二个参数是看他初不初始化,我们看到上有个另一个forname
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
{
Class<?> caller = null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Reflective call to get caller class is only needed if a security manager
// is present. Avoid the overhead of making this call otherwise.
caller = Reflection.getCallerClass();
if (sun.misc.VM.isSystemDomainLoader(loader)) {
ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
return forName0(name, initialize, loader, caller);
}
我们把第二个参数设置为false
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class.forName("org.example.Person",false,cl);
他啥也不输出
为什么会这样呢,因为他们都是用了Loader,它是用来初始化的
动态加载字节码
public class Main {
public static void main(String[] args) throws Exception {
ClassLoader c1 = ClassLoader.getSystemClassLoader();
Class<?> f = c1.loadClass("org.example.Person");
}
}
我们进入loadClass
,本来是会进入Launcher#loadClass
但是他没有只传一个参数的所以他会到他的父类URLClassLoader#loadClass
,可是还是没有,他会接着往上到SecureClassLoader#loadClass
,还是没有最后到ClassLoader#loadClass
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
接着进入Launcher#loadClass
public Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
int i = name.lastIndexOf('.');
if (i != -1) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPackageAccess(name.substring(0, i));
}
}
if (ucp.knownToNotExist(name)) {
// The class of the given name is not found in the parent
// class loader as well as its local URLClassPath.
// Check if this class has already been defined dynamically;
// if so, return the loaded class; otherwise, skip the parent
// delegation and findClass.
Class<?> c = findLoadedClass(name);
if (c != null) {
if (resolve) {
resolveClass(c);
}
return c;
}
throw new ClassNotFoundException(name);
}
return (super.loadClass(name, resolve));
}
然后我们一直走到最后面return (super.loadClass(name, resolve));
然后进去ClassLoader#loadClass
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;
}
}
我们来到这个判断
if (parent != null) {
c = parent.loadClass(name, false);
}
因为我们现在是在AppClassLoader
,所以他是有parent
所以可以进去,然后我们进去ClassLoader#loadClass
,然后还是回到了这里,但是ClassLoader
变成了ExtClassLoader
,接着进行判断,但是他的parent
为null,因为BootstrapClassLoader
是底层原生代码是 C 语言编写,(这里 null 是因为最上面的 Bootstrap 类是 native 类,也就是之前说过的 C 写的源码,所以为 null。)我们往下走,到了fineClass
,进去。会来到URLClassLoader#findClass
,可是找到不到,所以就出去这个函数。回到AppClassLoader
的loadClass
然后往下走到findClass
,进入到URLClassLoader#findClass
,这部分就是双亲委派,就是先一直往上走到最顶的ClassLoader
,然后fineClass
看看能不能找到这个类,如果不行就回到下一层看看找不找得到,ExtClassLoader
是找不到的,下一层,这个AppClassLoader
是可以找到的
protected Class<?> findClass(final String name)
throws ClassNotFoundException
{
final Class<?> result;
try {
result = AccessController.doPrivileged(
new PrivilegedExceptionAction<Class<?>>() {
public Class<?> run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
} else {
return null;
}
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (ClassNotFoundException) pae.getException();
}
if (result == null) {
throw new ClassNotFoundException(name);
}
return result;
}
ok我们进入URLClassLoader#defineClass
private Class<?> defineClass(String name, Resource res) throws IOException {
long t0 = System.nanoTime();
int i = name.lastIndexOf('.');
URL url = res.getCodeSourceURL();
if (i != -1) {
String pkgname = name.substring(0, i);
// Check if package already loaded.
Manifest man = res.getManifest();
definePackageInternal(pkgname, man, url);
}
// Now read the class bytes and define the class
java.nio.ByteBuffer bb = res.getByteBuffer();
if (bb != null) {
// Use (direct) ByteBuffer:
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, bb, cs);
} else {
byte[] b = res.getBytes();
// must read certificates AFTER reading bytes.
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, b, 0, b.length, cs);
}
}
我们接着进入return defineClass(name, b, 0, b.length, cs);
,到了他的父类SecureClassLoader#defineClass
protected final Class<?> defineClass(String name,
byte[] b, int off, int len,
CodeSource cs)
{
return defineClass(name, b, off, len, getProtectionDomain(cs));
}
然后再到他的父类ClassLoader#defineClass
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;
}
然后接着进入Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
private native Class<?> defineClass1(String name, byte[] b, int off, int len,
ProtectionDomain pd, String source);
他就把字节码加载好了
ClassLoader —-> SecureClassLoader —> URLClassLoader —-> APPClassLoader
loadclass --> findclass --> defineclass
利用URLClassLoader
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file:///D:\\ideaproject\\dongtaileijiazai\\target\\classes\\")});
Class<?> c = urlClassLoader.loadClass("org.example.test");
c.newInstance();
这里的file可以是jar/http/
标签:return,String,加载,class,loadClass,动态,Class,name From: https://www.cnblogs.com/20031225gbz/p/18374537