1、JVM基本结构:

*.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/*.jar】ClassLoader

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  》启动类加载器

在jdk的rt.jar下找到java.lang.classLoader类,找到类加载方法:

@parem:name,类的二进制字节流

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 2019年9月15日

*

*/

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();

}

探索JVM底层奥秘ClassLoader源码分析的更多相关文章

  1. 别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】

    目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.C ...

  2. JVM 类加载器ClassLoader源码学习笔记

    类加载 在Java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 类型可以是Class,Interface, 枚举等. Java虚拟机与程序的生命周期 在如下几种情况下,Java虚拟机 ...

  3. 探索drf执行流程之APIView源码分析

    Django REST framework 简介 现在新一代web应用都开始采用前后端分离的方式来进行,淘汰了以前的服务器端渲染的方式.而实现前后端分离是通过Django REST framework ...

  4. ClassLoader源码分析与实例剖析

    在之前已经对类加载器做了不少实验了,这次主要是来分析一下ClassLoader的源码,当然主要是先从理解官方给它的注释开始,为之后自定义类加载器打好坚石的基础,下面开始: 而从类的层次结构来看也能感受 ...

  5. Redis学习之底层链表源码分析

    Redis底层链表的源码分析: 一.链表结点的结构(单个结点): // listNode 双端链表节点 typedef struct listNode { // 前置节点 struct listNod ...

  6. JAVA ArrayList集合底层源码分析

    目录 ArrayList集合 一.ArrayList的注意事项 二. ArrayList 的底层操作机制源码分析(重点,难点.) 1.JDK8.0 2.JDK11.0 ArrayList集合 一.Ar ...

  7. [软件测试]网站压测工具Webbench源码分析

    一.我与webbench二三事 Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能.Webbench ...

  8. 网站(Web)压测工具Webbench源码分析

    一.我与webbench二三事 Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能.Webbench ...

  9. [五]类加载机制双亲委派机制 底层代码实现原理 源码分析 java类加载双亲委派机制是如何实现的

      Launcher启动类 本文是双亲委派机制的源码分析部分,类加载机制中的双亲委派模型对于jvm的稳定运行是非常重要的 不过源码其实比较简单,接下来简单介绍一下   我们先从启动类说起 有一个Lau ...

随机推荐

  1. Java8 Stream流方法

    流是Java API的新成员,它允许以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现).就现在来说,可以把它们看成遍历数据集的高级迭代器.此外,流还可以透明地并行处理,无需写任何多 ...

  2. 【转】SOA架构和微服务架构的区别

    SOA架构和微服务架构的区别 https://blog.csdn.net/zpoison/article/details/80729052

  3. Linux开机报错,提示根目录有错误,无法通过检测进入系统

    报错信息如下: VolGroup-lv_root contains a file system with errors, check forced. 修复方法:(因为我的是虚拟机,可以随意做备份,所以 ...

  4. [LeetCode] 276. Paint Fence 粉刷篱笆

    There is a fence with n posts, each post can be painted with one of the k colors. You have to paint ...

  5. [LeetCode] 207. Course Schedule 课程安排

    There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prer ...

  6. python jieba 词云

    #!/usr/bin/python # coding:utf-8 # 绘制一个<三体>全集词云 # pip install jieba # pip install matplotlib # ...

  7. mysql查看和修改最大连接数

    查看最大连接数 SHOW VARIABLES LIKE '%max_connections%'; 修改最大连接数 ;

  8. Module 'mysql' already loaded in Unknown on line 0解决方法

    Module 'mysql' already loaded in Unknown on line 0解决方法 直接进入php.ini 把;extension=mysql.so注释掉就好了

  9. Mybatis获取数据库自增主键

    一般我们都为将表中主键列设置为自增,当我们执行插入语句时,比如这样 //测试添加 Employee employee = new Employee(null, "jerry4",n ...

  10. 【面试】IP数据报格式分析

    (除选项外的报头区总共20个字节) 1)版本:IPV4/IPV6 2)头长度:报头区长度,用于计算数据区的开始位置,比如头长度为6,代表报头区长度为6*4个字节,头长度的单位为4字节,所以报头区长度不 ...