类的生命周期

加载-》验证-》准备-》解析-》初始化-》使用-》卸载

类加载过程

类加载包括以上的前五个过程:加载,验证,准备,解析,初始化

加载

1、主要完成三个工作

  • 通过类的完全限定名称来定位定义该类的二进制字节流
  • 将二进制字节流中的静态数据结构转化成方法区中的动态数据结构
  • 在堆中生成一个代表该类的Class对象,指向方法区的数据结构,作为访问方法区的入口

2、获取二进制字节流文件的途径

  • 从 ZIP 包读取,成为 JAR、EAR、WAR 格式的基础。
  • 从网络中获取,最典型的应用是 Applet。
  • 运行时计算生成,例如动态代理技术,在 java.lang.reflect.Proxy 使用 ProxyGenerator.generateProxyClass 的代理类的二进制字节流。
  • 由其他文件生成,例如由 JSP 文件生成对应的 Class 类

验证

验证类是合理可用的

1、文件格式验证:验证Class文件格式是否符合规范和是否能够被当前版本虚拟机解释

2、元数据验证:对类的元数据进行语义验证,确保元数据没有不符合java语义规范

3、字节码验证:对类的方法体进行验证,

4、符号引用验证:验证符号引用是否能够正确解析

准备

在方法区中为类变量分配内存,并赋予系统默认初始值,指0,null这种而不是代码中手工赋予的初始值

解析

将符号应用替换成直接引用

初始化

类的初始化时机

主动引用

1、调用new、getststic,putstatic,invokestatic(读取或设置静态变量,调用静态方法)

2、通过反射实例化

3、初始化子类时,若父类还没有被初始化,则要先初始化父类

4、虚拟机启动时,加载包含Main的主类

被动引用

1、子类引用父类的静态字段,不会初始化子类

2、初始化数组类,不会初始化该类

3、常量在编译阶段就会读到常量缓冲池中,读取类的常量不会引起类的初始化

有且只有以上主动引用的四种情况才会引起类的初始化

类加载器

类加载器的定义与作用

类加载器的作用就是根据类的全限定名称获取相对应的Class二进制字节流文件,并将其加载到虚拟机内部

意义:任何一个类的唯一性是由类本身和加载该类的类加载器一起确定的

(两个类相等,包括类的 Class 对象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回结果为 true,也包括使用 instanceof 关键字做对象所属关系判定结果为 true。)

分类

从虚拟机内部看

  • 启动类加载器(Bootstrap ClassLoader):用C++语言编写,是虚拟机的一部分
  • 其他类加载器:使用java实现,独立于虚拟机,继承于抽象类java.lang.ClassLoader

从开发人员角度看

  • 启动类加载器(BootStrap ClassLoader)
  • 扩展类加载器(Extension ClassLoader)
  • 应用程序类加载器(Application ClassLoader)

双亲委托模型

类加载器层次

工作过程

一个类加载器接到了加载类的请求,并不会立即加载,而是传递给它的上层类加载器,若上次类加载器无法加载,才会尝试自己加载

好处

使得 Java 类随着它的类加载器一起具有一种带有优先级的层次关系,从而使得基础类得到统一。

例如 java.lang.Object 存放在 rt.jar 中,如果编写另外一个 java.lang.Object 并放到 ClassPath 中,程序可以编译通过。

由于双亲委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 优先级更高,

这是因为 rt.jar 中的 Object 使用的是启动类加载器,而 ClassPath 中的 Object 使用的是应用程序类加载器。

rt.jar 中的 Object 优先级更高,那么程序中所有的 Object 都是这个 Object。

实现过程

loadClass() 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 ClassNotFoundException,此时尝试自己去加载。

 public abstract class ClassLoader {
// The parent class loader for delegation
private final ClassLoader parent; public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
} 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) {
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.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
} protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
}

自定义类加载器

1、继承java.lang.ClassLoader

2、不用重写loadClass方法,但是需要重写findClass方法

 public class FileSystemClassLoader extends ClassLoader {

     private String rootDir;

     public FileSystemClassLoader(String rootDir) {
this.rootDir = rootDir;
} protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
} else {
return defineClass(name, classData, 0, classData.length);
}
} private byte[] getClassData(String className) {
String path = classNameToPath(className);
try {
InputStream ins = new FileInputStream(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesNumRead;
while ((bytesNumRead = ins.read(buffer)) != -1) {
baos.write(buffer, 0, bytesNumRead);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
} private String classNameToPath(String className) {
return rootDir + File.separatorChar
+ className.replace('.', File.separatorChar) + ".class";
}
}

JVM系列四:类加载的更多相关文章

  1. jvm系列四类加载与字节码技术

    四.类加载与字节码技术 1.类文件结构 首先获得.class字节码文件 方法: 在文本文档里写入java代码(文件名与类名一致),将文件类型改为.java java终端中,执行javac X:...\ ...

  2. jvm系列 (五) ---类加载机制

    类的加载机制 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 jvm系列 (四) ---强.软.弱.虚引用 我的博客目录 什么是类 ...

  3. JVM总括四-类加载过程、双亲委派模型、对象实例化过程

    JVM总括四-类加载过程.双亲委派模型.对象实例化过程 目录:JVM总括:目录 一. 类加载过程 类加载过程就是将.class文件转化为Class对象,类实例化的过程,(User user = new ...

  4. jvm系列(四):jvm知识点总结

    原文链接:http://www.cnblogs.com/ityouknow/p/6482464.html jvm 总体梳理 jvm体系总体分四大块: 类的加载机制 jvm内存结构 GC算法 垃圾回收 ...

  5. jvm系列四、jvm知识点总结

    原文链接:http://www.cnblogs.com/ityouknow/p/6482464.html jvm 总体梳理 jvm体系总体分四大块: 类的加载机制 jvm内存结构 GC算法 垃圾回收 ...

  6. jvm系列 (四) ---强、软、弱、虚引用

    java引用 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 我的博客目录 为什么将引用分为不同的强度 因为我们需要实现这样一种情 ...

  7. 【JVM】JVM系列之类加载机制(四)

    一.前言 前面分析了class文件具体含义,接着需要将class文件加载到虚拟机中,这个过程是怎样的呢,下面,我们来仔细分析. 二.什么是类加载机制 把class文件加载到内存,并对数据进行校验.转换 ...

  8. jvm系列(四):jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)

    文章同步发布于github博客地址,阅读效果更佳,欢迎品尝 运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎 ...

  9. jvm系列(四):jvm调优-命令篇

    运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ...

随机推荐

  1. curl --resolve 查看证书情况

    通过curl  解析证书 [root@harbor ~]# curl --resolve 'www.abc.com:127.0.0.1' https://www.abc.com/ -vvv * Cou ...

  2. [US Open 2004][luogu2342] 叠积木 [带权并查集]

    题面 洛谷传送门 思路 害 学了4年多OI,第一次知道还有带权并查集这个东西 wtcl 这个玩意儿的原理和详细实现,可以参考这个博客:带权并查集传送门 这道题,就是在带权并查集的基础上,加个维护每个集 ...

  3. PHP提高in_array查找元素的方法

    PHP提高in_array查找元素的方法<pre><?php$arr = array(); // 创建10万个元素的数组for($i=0; $i<100000; $i++){ ...

  4. php类的继承(基本概念,访问权限修饰符,重写override)

    类的继承 简单理解: 某个类A具有某些特征,另一个类B,也具有A类的所有特征,并且还可能具有自己的更多的一些特征,此时,我们就可以实现:B类使用A的特征信息并继续添加自己的一些特有特征信息. 基本概念 ...

  5. CSS float属性

    表示向左浮动,比如多个div在一个页面上,默认情况是:一行一个div,但是只要在div的css中使用float:left,可以使一行有多个div,这样可以把网页划分成很多块,但是使用该属性会影响后面的 ...

  6. Http 请求到后端过程

    描述下网页一个 Http 请求,到后端的整个请求过程 评注:基础题,感觉属于常识题!必会! 回答: 利用DNS进行域名解析 -------> 发起TCP的3次握手 --------> 建立 ...

  7. 【剑指offer】面试题 52. 两个链表的第一个公共结点

    面试题 52. 两个链表的第一个公共结点 NowCoder 题目描述 输入两个链表,找出它们的第一个公共结点. Java 实现 ListNode Class class ListNode { int ...

  8. [转帖]AWS第一,「3A格局」稳固,活跃IP是如何被全球云厂商瓜分的?

    AWS第一,「3A格局」稳固,活跃IP是如何被全球云厂商瓜分的? 本文作者:王刚 2019-02-24 10:42 https://www.leiphone.com/news/201902/qsz3c ...

  9. [转帖]大数据hadoop与spark的区别

    大数据hadoop与spark的区别 https://www.cnblogs.com/adnb34g/p/9233906.html Posted on 2018-06-27 14:43 左手中倒影 阅 ...

  10. Linux基础-07-系统的初始化和服务

    1. Linux系统引导的顺序 1) Linux系统引导的顺序:                             其中,BIOS的工作是检查计算机的硬件设备,如CPU.内存和风扇速度等: MB ...