详解Class加载过程
1.Class文件内容格式

2.一个class文件是被加载到内存的过程是怎样的?
- loading
把一个class文件装到内存里,class文件是一个二进制,一个个的字节
- linking
- Verification:校验装载进来的class文件是不是符合jvm规定,如果不符合规范,直接就被拒掉了
- Preparation:把class文件静态变量赋默认值,比如int i = 8;那么此时i = 0而不是8
- Resolution:把class文件中的类、方法、属性等符号引用转换为直接引用,常量池里面用到的符号引用,解析为指针、偏移量等内存直接引用地址
- Initlalizing
给变量赋初始值int i = 8,上个步骤是0,到这一步才真正的赋值为8

一个class文件被加载到内存之后是创建了两块内容
1.分配一块内存用来存储class文件的内容
2.创建一个class对象,指向class文件内容的内存地址
3.类加载器


loading:双亲委派
定义:如果一个类加载器收到了加载某个类的请求,则该类加载器并不会直接去加载该类,而是把这个请求委派给父类加载器,如果父类加载器已经把这个类加载进内存,则直接返回,如果没有则继续委派给父加载器,以此类推,只有当父类加载器在其搜索范围内无法找到所需的类,并将该结果反馈给子类加载器,子类加载器会尝试去自己加载。

为什么需要双亲委派?
主要是为了安全。如果有人想替换系统级别的类:String.java。篡改它的实现,但是在这种机制下这些系统的类已经被Bootstrap classLoader加载过了,所以并不会再去加载,从一定程度上防止了危险代码的植入
父加载器
父加载器不是“类加载器的加载器”,也不是“类加载器的父类加载器”
在Launcher类(ClassLoader的一个包装启动类)中,可以看到类加载器范围
bootstartap

ext

app

4.自定义类加载器
- 定义一个类继承ClassLoader
- 重写模板方法:findClass,并在内部调用defineClass
load class---->findClass(模板方法/钩子函数)
public class OverrideFindClass extends ClassLoader {
/**
* 框架,类库,tomcat/spring都有自定义的类加载器
* 自定义类加载器
* 下面是思路:
* 1.把class文件以流的方式读入内存
* 2.调用classLoader的内置方法:defineClass
*
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
File file = new File("", name.replaceAll(".", "/").concat(".class"));
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = 0;
while ((b = fis.read()) != 0) {
baos.write(b);
}
byte[] bytes = baos.toByteArray();
baos.close();
//把二进制字节流转化为类
return defineClass(name, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
ClassLoader classLoader = new OverrideFindClass();
//name是指项目内,文件的包路径
Class clazz = classLoader.loadClass("classloader.Hello");
Hello hello = (Hello) clazz.newInstance();
hello.m();
System.out.println(classLoader.getClass().getClassLoader());
System.out.println(classLoader.getParent());
}
}
Java可以解释执行也可以即时编译
-Xmixed:默认混合模式,解释执行+热点代码编译
- 什么是热点代码编译?
多次被调用的方法,多次被调用的循环,内部维护了一个计数器,如果发现某个方法被执行了很多次,就会被编译为本地代码,再用的话就可以直接执行
- 既然即时编译运行速度这么快,为什么不直接都编译为本地代码呢?
第一:Java现在的解释器的效率已经非常高了,在一些代码的执行上也不输给编译器
第二:如果类库的类很多,二话不说直接编译,那速度必然是很慢很慢,所以就采用了混合模式
-Xint:解释模式,启动很快,执行稍慢
-Xcomp:纯编译模式,启动很慢,执行很快
自定义classLoader的父亲
- 继承ClassLoader
- 指定父加载器:super(parent)
public class SetClassLoaderParentBySelf {
static OverrideFindClass parent = new OverrideFindClass();
static class MyLoader extends ClassLoader {
public MyLoader(){
super(parent);
//不指定的话默认是AppClassLoader
//System.out.println(this.getParent());
}
}
public static void main(String[] args) {
MyLoader loader = new MyLoader();
}
}
5.打破双亲委派
如何打破?
- 重写loadClass
何时打破?
- jdk1.2之前,自定义classLoader都必须重写loadClass()
- 热启动,热部署:tomcat有自定义的classLoader(可以加在同一类库的不同版本,指不同应用,即每个应用都有自己的classLoader,所以出现同名不同版本的类库依然是可以都加载进来的)
如何自定义classLoader实现热部署的效果?
重写loadClass,干掉上一次加载的classLoader
public class DapoShuangQinWeiPai {
private static class MyLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
File file = new File("H:/Learning/jvm/src/main/java/" + name.replace(".", "/").concat(".class"));
if (!file.exists()) {
return super.loadClass(name);
}
try {
InputStream is = new FileInputStream(file);
byte[] b = new byte[is.available()];
is.read();
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
return super.loadClass(name);
}
}
public static void main(String[] args) {
MyLoader loader = new MyLoader();
try {
Class clazz = loader.loadClass("classloader.Hello");
loader = new MyLoader();
Class cla = loader.loadClass("classloader.Hello");
System.out.println(cla == clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
6.new对象的步骤
- 给对象申请内存
- 给对象的成员变量赋默认值
- 调用构造方法,给成员变量赋初始值
详解Class加载过程的更多相关文章
- 详解ListView加载网络图片的优化,让你轻松掌握!
详解ListView加载网络图片的优化,让你轻松掌握! 写博客辛苦了,转载的朋友请标明出处哦,finddreams(http://blog.csdn.net/finddreams/article/de ...
- linux modprobe命令参数及用法详解--linux加载模块命令
转:http://www.linuxso.com/command/modprobe.html modprobe(module probe) 功能说明:自动处理可载入模块. 语 法:modprobe [ ...
- Google推荐——Glide使用详解(图片加载框架)
零.前言 本文所使用的Glide版本为3.7.0 一.简介 Glide,一个被google所推荐的图片加载库,作者是bumptech.这个库被广泛运用在google的开源项目中,包括2014年的goo ...
- 详解ListView加载网络图片的优化
我们来了解一些ListView在加载大量网络图片的时候存在的常见问题: 1.性能问题,ListView的滑动有卡顿,不流畅,造成非常糟糕的用户体验. 2.图片的错位问题. 3.图片太大,加载Bitma ...
- web.xml的加载过程配置详解
一:web.xml加载过程 简单说一下,web.xml的加载过程.当我们启动一个WEB项目容器时,容器包括(JBoss,Tomcat等).首先会去读取web.xml配置文件里的配置,当这一步骤没有 ...
- <JVM中篇:字节码与类的加载篇>03-类的加载过程(类的生命周期)详解
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
- ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)
加载和动态链接 从编译/链接和运行的角度看,应用程序和库程序的连接有两种方式. 一种是固定的.静态的连接,就是把需要用到的库函数的目标代码(二进制)代码从程序库中抽取出来,链接进应用软件的目标映像中: ...
- linux内核剖析(零)linux系统启动过程详解-开机加电后发生了什么
本文参考了如下文章 深入理解linux启动过程 mbr (主引导记录(Master Boot Record)) 电脑从开机加电到操作系统main函数之前执行的过程 详解linux系统的启动过程及系统初 ...
- JVM——类的加载过程
附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...
随机推荐
- oeasy教您玩转linux010201持续输出yes
我们来回顾一下 上一部分我们都讲了什么?
- 使用docker部署hadoop集群
最近要在公司里搭建一个hadoop测试集群,于是采用docker来快速部署hadoop集群. 0. 写在前面 网上也已经有很多教程了,但是其中都有不少坑,在此记录一下自己安装的过程. 目标:使用doc ...
- Left Mouse Button (bfs)
Mine sweeper is a very popular small game in Windows operating system. The object of the game is to ...
- 发送post请求
题目: http://123.206.87.240:8002/post/ Brup抓包 1.修改Get 为 POST 2.添加 Content-Type: application/x-www-form ...
- 关于HTML基本标签,了解一下!
目录 1 前言 2 正文 2.1 HTML文档结构 2.1.1 html标签 2.1.2 head标签 2.1.3 title标签 2.1.4 body标签 2.2 HTML常用标签 2.2.1 换行 ...
- 【NOIP2013模拟】太鼓达人
题目描述 七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行.这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk.Poet_shy和lydrainbo ...
- Lambda表达式看这篇基本就够用了
本文讯] 2020.05.08 polo 写博不易,尊重知识! Lambda 是java8 引入的一个新特性,闭包,又叫函数式接口,下面介绍下,常用的lambda表达式方式: 所谓的将函数作为一 ...
- 2020重新出发,JAVA高级,JVM种设计模式
Java的23种设计模式全面解析 设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路.它不是语法规定,而是一套用来提高代码可复用性.可维护性.可读性.稳健 ...
- CentOS 7安装SeaweedFS
1.从GitHub下载编译好的SeaweedFS 地址:https://github.com/chrislusf/seaweedfs/releases 选择linux_amd64.tar.gz的压缩包 ...
- JVM字符串常量池StringTable
String的基本特性 String:字符串,使用一对""引起来表示. String sl = "hello"://字面量的定义方式: String s2 = ...