1.Class文件内容格式

2.一个class文件是被加载到内存的过程是怎样的?

  1. loading

把一个class文件装到内存里,class文件是一个二进制,一个个的字节

  1. linking
  • Verification:校验装载进来的class文件是不是符合jvm规定,如果不符合规范,直接就被拒掉了
  • Preparation:把class文件静态变量赋默认值,比如int i = 8;那么此时i = 0而不是8
  • Resolution:把class文件中的类、方法、属性等符号引用转换为直接引用,常量池里面用到的符号引用,解析为指针、偏移量等内存直接引用地址
  1. 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对象的步骤

  1. 给对象申请内存
  2. 给对象的成员变量赋默认值
  3. 调用构造方法,给成员变量赋初始值

详解Class加载过程的更多相关文章

  1. 详解ListView加载网络图片的优化,让你轻松掌握!

    详解ListView加载网络图片的优化,让你轻松掌握! 写博客辛苦了,转载的朋友请标明出处哦,finddreams(http://blog.csdn.net/finddreams/article/de ...

  2. linux modprobe命令参数及用法详解--linux加载模块命令

    转:http://www.linuxso.com/command/modprobe.html modprobe(module probe) 功能说明:自动处理可载入模块. 语 法:modprobe [ ...

  3. Google推荐——Glide使用详解(图片加载框架)

    零.前言 本文所使用的Glide版本为3.7.0 一.简介 Glide,一个被google所推荐的图片加载库,作者是bumptech.这个库被广泛运用在google的开源项目中,包括2014年的goo ...

  4. 详解ListView加载网络图片的优化

    我们来了解一些ListView在加载大量网络图片的时候存在的常见问题: 1.性能问题,ListView的滑动有卡顿,不流畅,造成非常糟糕的用户体验. 2.图片的错位问题. 3.图片太大,加载Bitma ...

  5. web.xml的加载过程配置详解

      一:web.xml加载过程 简单说一下,web.xml的加载过程.当我们启动一个WEB项目容器时,容器包括(JBoss,Tomcat等).首先会去读取web.xml配置文件里的配置,当这一步骤没有 ...

  6. <JVM中篇:字节码与类的加载篇>03-类的加载过程(类的生命周期)详解

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  7. ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)

    加载和动态链接 从编译/链接和运行的角度看,应用程序和库程序的连接有两种方式. 一种是固定的.静态的连接,就是把需要用到的库函数的目标代码(二进制)代码从程序库中抽取出来,链接进应用软件的目标映像中: ...

  8. linux内核剖析(零)linux系统启动过程详解-开机加电后发生了什么

    本文参考了如下文章 深入理解linux启动过程 mbr (主引导记录(Master Boot Record)) 电脑从开机加电到操作系统main函数之前执行的过程 详解linux系统的启动过程及系统初 ...

  9. JVM——类的加载过程

    附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...

随机推荐

  1. P3419 [POI2005]SAM-Toy Cars

    Description ​ Jasio 是一个三岁的小男孩,他最喜欢玩玩具了,他有n 个不同的玩具,它们都被放在了很高的架子上所以Jasio 拿不到它们. 为了让他的房间有足够的空间,在任何时刻地板上 ...

  2. python执行gradle脚本

    import os import shutil import subprocess #拷贝文件 def copyFile(srcFile, dstFile): #检查源文件是否存在 if not os ...

  3. 小花梨判连通 (bfs+思维+map统计数量)

    如果两个集合存储颜色的情况相同,说明这两个在k个图中都是在一个集合的 学到的点:用map,将vector映射一个整数时,只有vector后面的邻接的数据都一样时,才认为两个vector一样 代码: # ...

  4. 转贴:110个Oracle 函数

    转载地址:https://bbs.csdn.net/topics/310021870 1. ASCII返回与指定的字符对应的十进制数;SQL> select ascii(A) A,ascii(a ...

  5. Vue cli4 图片地址引入的几种方式

    五种图片地址引入方式 @开头,它也会作为一个模块请求被解析.它的用处在于Vue CLI默认会设置一个指向项目根目录/src的别名@

  6. React 和 VUE 的区别和优缺点

    前言 React 是由Facebook创建的JavaScript UI框架,React推广了 Virtual DOM( 虚拟 DOM )并创造了 JSX 语法.JSX 语法的出现允许我们在 javas ...

  7. oracle之WHERE子句中常用的运算符

    WHERE子句中常用的运算符 4.1 运算符及优先级: 算数运算符*,/,+,-, 逻辑运算符not, and ,or 比较运算符 单行比较运算 =,>, >=,<,<=, & ...

  8. Fiddler的安装和APP抓包

    前言 1.Fiddler安装包 2.安卓手机 3.iOS手机 1.下载fiddler软件:可以去官网下载https://www.telerik.com/fiddler,可以下载最新版 2.百度云盘(非 ...

  9. Unit5:广播

    静态广播 1.定义 public class TestBroadCast extends BroadcastReceiver { @Override public void onReceive(Con ...

  10. spring boot之AOP

    首先,aop是面向对象切面,嗯,就是说不面向静态方法,我做测试demo的时候controller方法有个加了static,尴尬的是就用了那个方法测,检查了几遍配置... 参看这篇文章https://m ...