探索JVM底层奥秘ClassLoader源码分析

1JVM基本结构:

*.java--------javac编译------>*.class-----ClassLoad加载---->运行时数据区------->执行引擎,接口库------>本地方法库

2、JVM运行流程:

 

public class Dome {

private static int tem=1;

static {

tem=2;

System.out.println(tem);

}

public static void main(String[] args) {

tem=6;

System.out.println(tem);

}

}

类的装载:

加载,连接(验证,准备,解析),初始化,使用,卸载

Class会保存类的定义或者结构到堆中

初始化:执行类的构造器《clinit》,为类的静态变量赋予正确的初始值

构造器:

1、static变量

2、Static{}语句块

构造方法:实列化对象

3、类加载器双亲委派模型

Bootstrat ClassLoader :启动类加载器(C++,内核)【rt.jar】  null

Extension ClassLoader:扩展类加载器---extends->%JAVA_HOME%/lib/ext/*.jarClassLoader

App ClassLoader:系统类加载器 ----extends-->Classpath下加载】ClassLoader扩展类加载器)

自定义类加载器: extends ClassLoader系统类加载器 ---【自定义加载】

public static void main(String[] args) {

//System.out.println(Dome2.class.getClassLoader());

ClassLoader classLoader=Dome2.class.getClassLoader();

while(classLoader!=null) {

System.out.println(classLoader);

classLoader=classLoader.getParent();

}

System.out.println(classLoader);

}

编译:

sun.misc.Launcher$AppClassLoader@2a139a55   》系统类加载器

sun.misc.Launcher$ExtClassLoader@7852e922   》扩展类型加载器

Null  》启动类加载器

jdkrt.jar下找到java.lang.classLoader类,找到类加载方法:

@paremname,类的二进制字节流

  public Class<?> loadClass(String name) throws ClassNotFoundException{

        return loadClass(name, false);

   }

查找是否有这个类:

有:从父类中加载

无:从BootstrapClass加载

//parent:

  // The parent class loader for delegation

    // Note: VM hardcoded the offset of this field, thus all new fields

// must be added *after* it

private final ClassLoader parent;//父类委派机制 :包含关系

 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;

        }

    }

被子类重写:

 protected Class<?> findClass(String name) throws ClassNotFoundException {

        throw new ClassNotFoundException(name);

}

实列:自定义类加载器

一个本地的Demo.class文件,一个编译环境中的Demo.class文件

测试调用类:

public class Dome {

public Dome() {

System.out.println("A Dome"+Dome.class.getClassLoader());

}

}

需求实现类:

package com.cn.classload;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

/**

 * @Description: 自定义类加载器

 * @ClassName: MyClassLoader

 * @author

 * @date 2019915

 *

 */

public class MyClassLoader extends ClassLoader {

private String path;// 加载类的路劲

private String name;// 类加载器名称

public MyClassLoader(String name, String path) {

super();// 让系统类加载器成为该类的父类

this.name = name;

this.path = path;

}

// 父类委托机制:父类加载器

public MyClassLoader(ClassLoader parent, String name, String path) {

super(parent);

this.name = name;

this.path = path;

}

/**

 * 加载自定义的ClassLoader Title: findClass Description:

 *

 * @param name:包路径

 * @return

 * @throws ClassNotFoundException

 * @see java.lang.ClassLoader#findClass(java.lang.String)

 *

 */

@Override

protected Class<?> findClass(String name) throws ClassNotFoundException {

byte[] data = readClassFileToByteArray(name);

return this.defineClass(name, data, 0, data.length);

}

/**

 * Title: toString Description:

 *

 * @return

 * @see java.lang.Object#toString()

 *

 */

@Override

public String toString() {

// TODO Auto-generated method stub

return this.name;

}

/**

 * @Description: 获取.class文件的字节数组

 * @Title: readClassFileToByteArray

 * @date 2019-09-15 17:27

 * @param @param name2

 * @param @return 参数

 * @return byte [] 返回类型

 * @throws @return byte []

 * @param name2

 * @return

 */

private byte[] readClassFileToByteArray(String name) {

InputStream iStream = null;

byte[] returnData = null;

name = name.replaceAll("\.", "/");

String filePath = this.path + name + ".class";

System.out.println("路径:"+filePath);

File file = new File(filePath);

ByteArrayOutputStream os = new ByteArrayOutputStream();

try {

iStream = new FileInputStream(file);

int tmp = 0;

while ((tmp = iStream.read()) != -1) {

os.write(tmp);

}

returnData = os.toByteArray();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

if (os != null) {

try {

os.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

if (iStream != null) {

try {

iStream.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

return returnData;

}

}

测试类:

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

MyClassLoader zhangfeimyClassLoader=new MyClassLoader("zhangfei","D:/com/cn/classload/");

//MyClassLoader wukongmyClassLoader=new MyClassLoader(zhangfeimyClassLoader,"wukong","D:/com/cn/classload/");//现在张飞是悟空的父类委派加载器输出的就是编译环境中的Dome.class文件

MyClassLoader wukongmyClassLoader=new MyClassLoader(null,"wukong","D:/com/cn/classload/");//这里父类没有就是用自定义的加载器输出的就是本地磁盘上的Dome.class文件

Class<?> c=wukongmyClassLoader.loadClass("Dome");

c.newInstance();

}

学着把生活的苦酒当成饮料一样慢慢品尝, 不论生命经过多少委屈和艰辛, 我们总是以一个朝气蓬勃的面孔, 醒来在每一个早上。
原文地址:https://www.cnblogs.com/yhm9/p/11525564.html