深入理解JVM—类加载 part2

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值