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. 初学WebGL引擎-BabylonJS:第3篇-方向纹理与相机

    [playground]-rotatuib abd scaling(方向) 源码 var createScene = function () { var scene = new BABYLON.Sce ...

  2. 实现:git本地创建多个分支互不干扰

    git本地创建多个分支互不干扰 在项目开发过程中,经常会遇到下面这种情况: 业务情景:在做某个需求a时,先需要修改紧急bug b:发版时发的是远程dev的代码 方式一(推荐): (1)本地已有分支de ...

  3. 常用API【2】

    常用API 1.Math类 1.1 Math类概述 Math包含执行基本数字运算的方法 没有构造方法,如何使用类中的成员呢? 看类的成员是否是静态的,如果是,可以通过类名直接调用 1.2Math类的常 ...

  4. uap设置gradle和jdk

  5. boot 项目启动报Cannot datermine embedded database driver class for database type NONE

    部署boot项目时报Cannot datermine embedded database driver class for database type NONE数据库链接什么的也都没有问题,经过百度 ...

  6. python基础:多进程、多线程

    一.定义和区别 1.一个任务就是一个进程,进程就是资源的集合.比如打开浏览器,启动一个进程.当一个进程需要干很多事的时候,就需要执行多个子任务,这些子任务就是线程. 2.线程是包含在进程中的,每个进程 ...

  7. do...while 循环

    语法 C 语言中 do...while 循环的语法: do { statement(s); }while( condition ); 请注意,条件表达式出现在循环的尾部,所以循环中的 statemen ...

  8. IDEA 2020.2安装破解版教程激活码注册码破解补丁 for Mac Windows Linux-中关村老大爷

    IntelliJ Idea Ultimate 2020.2.x版软件最新安装破解版教程方法,本教程提供Idea Ultimate 2020.2版安装包,破解补丁,激活码,亲测100%完美破解激活,支持 ...

  9. [Node]创建静态资源服务器

    项目初始化 .gitignore cnpm i eslint -D eslint --init得到.eslintrc.js .eslintrc.js module.exports = { 'env': ...

  10. native到CPU

    Native 所谓的native准确的说是借由虚拟机实现的JNI接口调用的操作系统提供的API JNI使得class中的ACC_NATIVE标至的方法能借由JNI类的实例转换为JNI规范(如全限定名) ...