Demo11 | package com.optimize.learnJVM.classloader;
public class MyTest11 { public static void main(String[] args) { System.out.println(Child3.a); Child3.doSomeThing(); } }
class Parent3 { static int a = 3;
static { System.out.println("Parent3 static block"); }
static void doSomeThing() { System.out.println("do something"); } }
class Child3 extends Parent3 { static { System.out.println("Child3 static block"); } }
//输出 //Parent3 static block //3 //do something
//解释:没有使用到Child的任何数据,没有对其产生一个主动使用。 //总结:通过子类的名称,调用父类的静态变量和静态方法(谁拥有就是主动使用谁),本质上都是对父类的主动使用,而非子类。 |
Demo12 | package com.optimize.learnJVM.classloader;
public class MyTest12 { public static void main(String[] args) throws Exception { ClassLoader loader = ClassLoader.getSystemClassLoader(); Class<?> clazz = loader.loadClass("com.optimize.learnJVM.classloader.CL"); System.out.println(clazz); System.out.println("------------"); clazz = Class.forName("com.optimize.learnJVM.classloader.CL"); System.out.println(clazz); } }
class CL{ static { System.out.println("Class CL "); } }
//输出 //class com.optimize.learnJVM.classloader.CL //------------ //Class CL //class com.optimize.learnJVM.classloader.CL
//调用ClassLoader类的loadClass方法加载一个类, 并不是对类的主动使用,不会导致类的初始化 |
Demo13 | package com.optimize.learnJVM.classloader;
public class MyTest13 { public static void main(String[] args) throws Exception { ClassLoader loader = ClassLoader.getSystemClassLoader(); System.out.println(loader); System.out.println("-----------"); while (loader!=null){ loader = loader.getParent(); System.out.println(loader); }
} }
//输出 //sun.misc.Launcher$AppClassLoader@18b4aac2 //----------- //sun.misc.Launcher$ExtClassLoader@5a07e868 //null
获得当前类的ClassLoader:clazz.getClassLoader(); 获得当前线程上下文的ClassLoader:Thread.currentThread().getContextClassLoader() 获得系统的ClassLoader:ClassLoader.getSystemClassLoader() 获得调用者的ClassLoader:DriverManager.getCallerClassLoader() |
Demo14 | package com.optimize.learnJVM.classloader;
import java.io.IOException; import java.net.URL; import java.util.Enumeration;
public class MyTest14 { public static void main(String[] args) throws IOException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); System.out.println(classLoader); String resourceName = "com/optimize/learnJVM/classloader/MyTest13.class";
Enumeration<URL> urls = classLoader.getResources(resourceName); while (urls.hasMoreElements()){ URL url = urls.nextElement(); System.out.println(url); } } }
//输出 //sun.misc.Launcher$AppClassLoader@18b4aac2 //file:/Users/shijiazhang/AndroidStudioProjects/androidperformance/app/build/intermediates/classes/debug/com/optimize/learnJVM/classloader/MyTest13.class
//资源在磁盘上的全路径 |
Demo15 | package com.optimize.learnJVM.classloader;
public class MyTest15 { public static void main(String[] args) { String[] strings = new String[2]; System.out.println(strings.getClass().getClassLoader());
System.out.println("-------------");
MyTest15[] myTest15s = new MyTest15[2]; System.out.println(myTest15s.getClass().getClassLoader());
System.out.println("-------------");
int[] ints = new int[2]; System.out.println(ints.getClass().getClassLoader()); } }
//输出 //null 表示启动类加载器 //------------- //sun.misc.Launcher$AppClassLoader@18b4aac2 //------------- //null 表示没有类加载器的 if the element type is a primitive type,then the array class has no class loader。
//解释 //Class objects for array classes are not created by class loaders, //but are created automatically as required by the Java runtime. //The class loader for an array class, as returned by Class.getClassLoader() is the same as //the class loader for its element type; if the element type is a primitive type, //then the array class has no class loader. |
Demo16-1 | package com.optimize.learnJVM.classloader;
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream;
public class MyTest16 extends ClassLoader { private String classLoaderName;
private final String fileExtension = ".class";
public MyTest16(String classLoaderName) { super();//将系统类加载器当做该类加载器的父加载器 this.classLoaderName = classLoaderName; }
public MyTest16(ClassLoader parent, String classLoaderName) { super(parent);//显式指定加载器的父加载器 this.classLoaderName = classLoaderName; }
@Override protected Class<?> findClass(String className) throws ClassNotFoundException { System.out.println("findClass invoked :" + className); System.out.println("class loader name:" + this.classLoaderName); byte[] data = this.loadClassData(className); return defineClass(className, data, 0, data.length); }
private byte[] loadClassData(String name) { InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null;
try { this.classLoaderName = this.classLoaderName.replace(".", "/");
is = new FileInputStream(new File(name + this.fileExtension)); baos = new ByteArrayOutputStream();
int ch; while (-1 != (ch = is.read())) { baos.write(ch); }
data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { is.close(); baos.close(); } catch (IOException e) { e.printStackTrace(); } } return data; }
public static void test(ClassLoader classLoader) throws Exception { Class<?> clazz = classLoader.loadClass("com.optimize.learnJVM.classloader.MyTest1"); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader()); }
public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); test(loader1); } }
//输出 //com.optimize.learnJVM.classloader.MyTest1@5a07e868 //sun.misc.Launcher$AppClassLoader@18b4aac2 //并不是我们的MyTest16类加载器加载的,那么问题出现在哪里呢?
// MyTest16 loader1 = new MyTest16("loader1");我们使用的这种方式,使用的是MyTest16父类加载作为parent的,MyTest16的父加载器是系统类加载器,能在classpath中找到相关的文件就直接加载了。 |
Demo16-2 | package com.optimize.learnJVM.classloader;
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream;
public class MyTest16 extends ClassLoader { private String classLoaderName;
private String path;//磁盘加载路径
private final String fileExtension = ".class";
public MyTest16(String classLoaderName) { super();//将系统类加载器当做该类加载器的父加载器 this.classLoaderName = classLoaderName; }
public MyTest16(ClassLoader parent, String classLoaderName) { super(parent);//显式指定加载器的父加载器 this.classLoaderName = classLoaderName; }
public void setPath(String path) { this.path = path; }
@Override public String toString() { return "MyTest16{" + "classLoaderName='" + classLoaderName + '\'' + '}'; }
@Override protected Class<?> findClass(String className) throws ClassNotFoundException { System.out.println("findClass invoked :" + className); System.out.println("class loader name:" + this.classLoaderName); byte[] data = this.loadClassData(className); return defineClass(className, data, 0, data.length); }
private byte[] loadClassData(String className) { InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null;
className = className.replace('.', '/');
try { this.classLoaderName = this.classLoaderName.replace(".", "/");
is = new FileInputStream(new File(this.path + className + this.fileExtension)); baos = new ByteArrayOutputStream();
int ch; while (-1 != (ch = is.read())) { baos.write(ch); }
data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { is.close(); baos.close(); } catch (IOException e) { e.printStackTrace(); } } return data; }
public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); //通过路径去加载 // loader1.setPath("/Users/shijiazhang/AndroidStudioProjects/androidperformance/app/build/intermediates/classes/debug/");
loader1.setPath("/Users/shijiazhang/Desktop/"); Class<?> clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz.hashCode()); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader());
System.out.println();
MyTest16 loader2 = new MyTest16(loader1,"loader2"); loader2.setPath("/Users/shijiazhang/Desktop/"); Class<?> clazz2 = loader2.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz2.hashCode()); Object object2 = clazz2.newInstance(); System.out.println(object2); System.out.println(object2.getClass().getClassLoader());
System.out.println();
MyTest16 loader3 = new MyTest16(loader2,"loader3"); loader3.setPath("/Users/shijiazhang/Desktop/"); Class<?> clazz3 = loader3.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz3.hashCode()); Object object3 = clazz3.newInstance(); System.out.println(object3); System.out.println(object3.getClass().getClassLoader()); } }
//输出 //com.optimize.learnJVM.classloader.MyTest1@5a07e868 //sun.misc.Launcher$AppClassLoader@18b4aac2 //并不是我们的MyTest16类加载器加载的,那么问题出现在哪里呢?
// MyTest16 loader1 = new MyTest16("loader1");我们使用的这种方式,使用的是MyTest16父类加载作为parent的。
// mkdir -p ~/Desktop/com/optimize/learnJVM/classloader // cp /Users/shijiazhang/AndroidStudioProjects/androidperformance/app/build/intermediates/classes/debug/com/optimize/learnJVM/classloader/MyTest1.class ~/Desktop/com/optimize/learnJVM/classloader
//删除文件中的MyTest1在运行
//输出 //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@3fee733d //MyTest16{classLoaderName='loader1'}
//解释: //将工程中的MyTest1删除,并去加载桌面中的MyTest1。 //当加载的时候系统类加载器找不到工程中的MyTest1,之后转移给自定义的MyTest16去加载
//将MyTest1添加回来 //输出 //class : 1510467688 //com.optimize.learnJVM.classloader.MyTest1@76ed5528 //sun.misc.Launcher$AppClassLoader@18b4aac2
//添加loader2 //输出 //class : 1510467688 //com.optimize.learnJVM.classloader.MyTest1@76ed5528 //sun.misc.Launcher$AppClassLoader@18b4aac2 //class : 1510467688 //com.optimize.learnJVM.classloader.MyTest1@2c7b84de //sun.misc.Launcher$AppClassLoader@18b4aac2 //一个类只会加载一次(在同一个命名空间内)
//删除MyTest1 //输出 //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@3fee733d //MyTest16{classLoaderName='loader1'} // //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader2 //class : 918221580 //com.optimize.learnJVM.classloader.MyTest1@7a81197d //MyTest16{classLoaderName='loader2'} //由于命名空间不同导致的加载2次相同的类
// 设置loader2的父加载器为loader1 // MyTest16 loader2 = new MyTest16(loader1,"loader2"); //输出 //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@3fee733d //MyTest16{classLoaderName='loader1'} // //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@5acf9800 //MyTest16{classLoaderName='loader1'}
//设置loader3 // MyTest16 loader3 = new MyTest16("loader3"); //输出 //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@3fee733d //MyTest16{classLoaderName='loader1'} // //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@5acf9800 //MyTest16{classLoaderName='loader1'} // //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader3 //class : 2055281021 //com.optimize.learnJVM.classloader.MyTest1@5ca881b5 //MyTest16{classLoaderName='loader3'}
// MyTest16 loader3 = new MyTest16(loader2,"loader3"); //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@3fee733d //MyTest16{classLoaderName='loader1'} // //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@5acf9800 //MyTest16{classLoaderName='loader1'} // //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@4617c264 //MyTest16{classLoaderName='loader1'} |
Demo16-3 | package com.optimize.learnJVM.classloader;
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream;
public class MyTest16 extends ClassLoader { private String classLoaderName;
private String path;//磁盘加载路径
private final String fileExtension = ".class";
public MyTest16(String classLoaderName) { super();//将系统类加载器当做该类加载器的父加载器 this.classLoaderName = classLoaderName; }
public MyTest16(ClassLoader parent, String classLoaderName) { super(parent);//显式指定加载器的父加载器 this.classLoaderName = classLoaderName; }
public void setPath(String path) { this.path = path; }
@Override public String toString() { return "MyTest16{" + "classLoaderName='" + classLoaderName + '\'' + '}'; }
@Override protected Class<?> findClass(String className) throws ClassNotFoundException { System.out.println("findClass invoked :" + className); System.out.println("class loader name:" + this.classLoaderName); byte[] data = this.loadClassData(className); return defineClass(className, data, 0, data.length); }
private byte[] loadClassData(String className) { InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null;
className = className.replace('.', '/');
try { this.classLoaderName = this.classLoaderName.replace(".", "/");
is = new FileInputStream(new File(this.path + className + this.fileExtension)); baos = new ByteArrayOutputStream();
int ch; while (-1 != (ch = is.read())) { baos.write(ch); }
data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { is.close(); baos.close(); } catch (IOException e) { e.printStackTrace(); } } return data; }
public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); //通过路径去加载 // loader1.setPath("/Users/shijiazhang/AndroidStudioProjects/androidperformance/app/build/intermediates/classes/debug/");
loader1.setPath("/Users/shijiazhang/Desktop/"); Class<?> clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz.hashCode()); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader());
System.out.println();
loader1 = new MyTest16("loader1"); loader1.setPath("/Users/shijiazhang/Desktop/"); clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz.hashCode()); object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader());
} }
//输出 //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@3fee733d //MyTest16{classLoaderName='loader1'} // //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 918221580 //com.optimize.learnJVM.classloader.MyTest1@7a81197d //MyTest16{classLoaderName='loader1'}
//两次加载的确实不一样,但不一定是被卸载了
public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); //通过路径去加载 // loader1.setPath("/Users/shijiazhang/AndroidStudioProjects/androidperformance/app/build/intermediates/classes/debug/");
loader1.setPath("/Users/shijiazhang/Desktop/"); Class<?> clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz.hashCode()); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader());
System.out.println(); loader1 = null; clazz = null; object = null; System.gc();
loader1 = new MyTest16("loader1"); loader1.setPath("/Users/shijiazhang/Desktop/"); clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz.hashCode()); object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader());
}
//添加-XX:+TraceClassUnloading //输出 //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 746292446 //com.optimize.learnJVM.classloader.MyTest1@3fee733d //MyTest16{classLoaderName='loader1'} // //[Unloading class com.optimize.learnJVM.classloader.MyTest1 0x00000007c0061028] //findClass invoked :com.optimize.learnJVM.classloader.MyTest1 //class loader name:loader1 //class : 918221580 //com.optimize.learnJVM.classloader.MyTest1@7a81197d //MyTest16{classLoaderName='loader1'}
public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); //通过路径去加载 // loader1.setPath("/Users/shijiazhang/AndroidStudioProjects/androidperformance/app/build/intermediates/classes/debug/");
loader1.setPath("/Users/shijiazhang/Desktop/"); Class<?> clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz.hashCode()); Object object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader());
System.out.println();
loader1 = null; clazz = null; object = null;
Thread.sleep(200000);
System.gc();
loader1 = new MyTest16("loader1"); loader1.setPath("/Users/shijiazhang/Desktop/"); clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MyTest1"); System.out.println("class : " + clazz.hashCode()); object = clazz.newInstance(); System.out.println(object); System.out.println(object.getClass().getClassLoader());
}
//线程睡眠20秒 //终端打开jvisualvm //选择启动的进程 //选择监视 查看类的已装入的总数和已卸载的总数变化 //如果我们添加看MyTest1,使的其又系统类加载器加载的话,就不会出现类卸载的情况。
|
Demo17-1 | package com.optimize.learnJVM.classloader;
public class MyCat { public MyCat() { System.out.println("MyCat is loaded by:" + this.getClass().getClassLoader()); } }
package com.optimize.learnJVM.classloader;
public class MySample { public MySample() { System.out.println("MySample is loaded by:" + this.getClass().getClassLoader()); new MyCat();//创建MyCat,使两个类产生关联 } }
package com.optimize.learnJVM.classloader;
public class MyTest17 { public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); Class<?> clazz = loader1.loadClass("com.optimize.learnJVM.classloader.MySample"); System.out.println("class : " + clazz.hashCode()); //如果注释掉该行,那么并不会实例化MySample对象,即MySample构造方法不会被调用 //因此不会实例化MyCat对象,即没有对MyCat进行主动使用个,这里就不会加载Mycat Class Object object = clazz.newInstance();
} }
//输出 //class : 1995265320 //MySample is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2 //MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2 // //注释掉Object object = clazz.newInstance(); //只是加载,但是没有生成实例,因此没有执行到构造方法。其实不一定加载mycat //可以通过-XX:+TraceClassLoading,用于追踪类的加载信息并打印出来
//解释 //类加载器并不需要等到某个类被“首次主动使用”时再加载它 //●JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到了.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(LinkageError错误) //●如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误 |
Demo17-2 | package com.optimize.learnJVM.classloader;
/** * 关于命名空间重要说明 * 1.子加载器所加载的类能够访问父加载器所加载的类 * 2.父加载器所加载的类无法访问子加载器所加载的类 */ public class MyTest17_1 { public static void main(String[] args) throws Exception { MyTest16 loader1 = new MyTest16("loader1"); loader1.setPath("/Users/shijiazhang/Desktop/"); Class<?> clazz = loader1.loadClass("com.shengsiyuan.jvm.classloader.MySample"); System.out.println("class : " + clazz.hashCode()); //如果注释掉该行,那么并不会实例化MySample对象,即MySample构造方法不会被调用 //因此不会实例化MyCat对象,即没有对MyCat进行主动使用个,这里就不会加载Mycat Class Object object = clazz.newInstance();
} }
//classes文件中删除MySample和MyCat //findClass invoked :com.optimize.learnJVM.classloader.MySample //class loader name:loader1 //class : 1072591677 //MySample is loaded by:MyTest16{classLoaderName='loader1'} //findClass invoked :com.optimize.learnJVM.classloader.MyCat //Mycat在MySample里也是由MyTest16进行加载 //class loader name:loader1 //MyCat is loaded by:MyTest16{classLoaderName='loader1'} // //删除class文件中的Mycat //class : 1627674070 //MySample is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2 //Exception in thread "main" java.lang.NoClassDefFoundError: com/shengsiyuan/jvm/classloader/MyCat // at com.shengsiyuan.jvm.classloader.MySample.<init>(MySample.java:6) // at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) // at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) // at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) // at java.lang.reflect.Constructor.newInstance(Constructor.java:423) // at java.lang.Class.newInstance(Class.java:442) // at com.shengsiyuan.jvm.classloader.MyTest17_1.main(MyTest17_1.java:11) //Caused by: java.lang.ClassNotFoundException: com.shengsiyuan.jvm.classloader.MyCat // at java.net.URLClassLoader.findClass(URLClassLoader.java:382) // at java.lang.ClassLoader.loadClass(ClassLoader.java:424) // at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) // at java.lang.ClassLoader.loadClass(ClassLoader.java:357) // ... 7 more // //Process finished with exit code 1 // //删除class文件中的MySample //findClass invoked :com.shengsiyuan.jvm.classloader.MySample //class loader name:loader1 //class : 1625635731 //MySample is loaded by:MyTest16{classLoaderName='loader1'} //MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2//MyTest16委托父加载去加载,由系统类加载器加载成功 // // //在MyCat中添加了对MySample的使用,再删除class文件中的MySample //public class MyCat { // public MyCat() { // System.out.println("MyCat is loaded by:" + this.getClass().getClassLoader()); // System.out.println("from MyCat : "+MySample.class); // } //} //findClass invoked :com.shengsiyuan.jvm.classloader.MySample //class loader name:loader1 //class : 1625635731 //MySample is loaded by:MyTest16{classLoaderName='loader1'} //MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2 //Exception in thread "main" java.lang.NoClassDefFoundError: com/shengsiyuan/jvm/classloader/MySample // at com.shengsiyuan.jvm.classloader.MyCat.<init>(MyCat.java:6) // at com.shengsiyuan.jvm.classloader.MySample.<init>(MySample.java:6) // at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) // at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) // at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) // at java.lang.reflect.Constructor.newInstance(Constructor.java:423) // at java.lang.Class.newInstance(Class.java:442) // at com.shengsiyuan.jvm.classloader.MyTest17_1.main(MyTest17_1.java:11) //Caused by: java.lang.ClassNotFoundException: com.shengsiyuan.jvm.classloader.MySample // at java.net.URLClassLoader.findClass(URLClassLoader.java:382) // at java.lang.ClassLoader.loadClass(ClassLoader.java:424) // at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) // at java.lang.ClassLoader.loadClass(ClassLoader.java:357) // ... 8 more // //解释:命名空间 //每个类加载器都有自己的命名空间,命名空间由该加载器及所有父加载器所加载的类组成。 // 在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类 // 在不同的命名空间中,有可能会出现类的完整名字(包括类的包名)相同的两个类。 // 父加载加载的类看不到子加载加载的类(AppClassLoader看不到MyTest16加载的MySample)
//子的命名空间访问父的命名空间的MyCat //在MySample也引用MyCat //public class MySample { // public MySample() { // System.out.println("MySample is loaded by:" + this.getClass().getClassLoader()); // new MyCat();//创建MyCat,使两个类产生关联 // // System.out.println("from MyCat : "+MyCat.class); // } //} //public class MyCat { // public MyCat() { // System.out.println("MyCat is loaded by:" + this.getClass().getClassLoader()); System.out.println("from MyCat : "+MySample.class); // } //} //输出 //findClass invoked :com.shengsiyuan.jvm.classloader.MySample //class loader name:loader1 //class : 1625635731 //MySample is loaded by:MyTest16{classLoaderName='loader1'} //MyCat is loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2 //from MyCat : class com.shengsiyuan.jvm.classloader.MyCat |
深入理解JVM—类加载 part2
最新推荐文章于 2024-01-29 09:07:49 发布