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. dataTable.NET的column index的不同定義

    dataTable.NET是一個jQuery的plug in 第三方的library, 用來實現web page中table的interaction controls, 另外最近有在用的還有Teler ...

  2. rabbitmq设置消息优先级、队列优先级配置

    1.首先在consume之前声明队列的时候,要加上x-max-priority属性,一般为0-255,大于255出错  -----配置队列优先级 配置成功后rabbitmq显示: 2.在向exchan ...

  3. 通过ip远程控制电脑

    现在,很多人都用了不止一台电脑,而同时操作两台电脑是一件比较麻烦的事情,所以,如果能够使用一台电脑的鼠标键盘显示器,去远程控制另一台电脑,那就方便多了. 远程计算机设置 1.先确保本地计算机和远程计算 ...

  4. harbor的安装和简单使用【h】

    安装docker的私有仓库, 利用vmware提供的harbor工具, 参考Docker 私有仓库方案比较与搭建, Harbor安装 -- 企业级Registry仓库 2.2harborProject ...

  5. 高级UI-Path和PathMeasure

    Path是一个工具类,用来记录线条的轨迹路径,然后通过绘制轨迹路径,可以得到各种各样的图案,而PathMeasure是用来对Path进行测量的工具,再Path的运用中,运用最多的就是贝塞尔曲线,也是本 ...

  6. 面试之leetcode两数求和

    1 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样 ...

  7. (转)面试前必知Redis面试题—缓存雪崩+穿透+缓存与数据库双写一致问题

    背景:redis问题在面试过程中经常被问到,对于常见问题一定不能放过. 面试前必知Redis面试题—缓存雪崩+穿透+缓存与数据库双写一致问题 一.缓存雪崩 1.1什么是缓存雪崩? 如果缓存数据设置的过 ...

  8. 了解一下JVM和GC工作机制

    题外话:很久没有写博客了,事情颇多,今天空闲下来,学习一下顺便写一下自己的了解,机会总是留给有准备的人,所以平常一定要注意知识的巩固和积累.知识的深度也要有一定的理解,不比别人知道的多,公司干嘛选你? ...

  9. LeetCode 32. 最长有效括号(Longest Valid Parentheses) 31

    32. 最长有效括号 32. Longest Valid Parentheses 题目描述 给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 每日一算法2019/6/ ...

  10. JavaWeb实现增删查改(图书信息管理)之删除功能实现

    —————————————————————————————————————————————————————————— 删除按钮对应的servlet -->DeleteBooks.java  ↓ ...