Java高级之虚拟机加载机制

简介:   本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!1.0版本:2016-05-21 1.



  本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!

1.0版本:2016-05-21 

1.1版本:2016-10-22

前两节我们探讨了Java类内存模块,文件结构,以及Jvm的回收机制,今天我们再来探讨一下它的文件加载机制,都知道Jvm要加载的是二进制流,可以是.class文件形式,也可以是其他形式,总之按照它加载的标准即协议来设计就不会有问题,以下主要就机制和标准两个问题分析一番

首先来说Java类文件的加载机制,跟变量的加载机制类似,它先把Class文件加载入内存,再对数据进行验证、解析和初始化,最终形成虚拟机可以直接使用的Java类型。由于Java是采用JIT机制,所以加载时会比较慢,但优点也明显,具有高度灵活性,支持动态加载和动态连接。接下来就讲讲类的加载过程:

一个类加载的基本过程是按照下面的顺序来,但也有不严格按照这个顺序来的,也有打乱顺序来的,如动态加载就得先初始化再解析。

1、加载- 由虚拟机自行决定,但也有由于下面的阶段要执行而执行上面阶段的情况。这时虚拟机会做三件事,第一、通过全限定名找到文件,读取它的二进制流,第二、把文件里的静态方法和变量放到方法区中,第三、生成一个对象放入堆中,作为访问入口。注意第一条,仅是读取二进制流,没说具体从什么文件中读,也没说从哪里读,所以造就Java很强的扩展性,可以从Jar、Zip中,也可以从网络层、数据库层等 。主要是对象和方法区的声明。

2、验证 确保二进制流符合虚拟机的要求,不符合会报VerifyError。 第一、文件格式验证,是否符合Java文件的要求:如是否有魔数,主次版本是否符合当前虚拟机要求(详见:Java高级之类结构的认识;第二、元数据验证,是否符合Java代码规范,如abstract类是否直接被实例化或子类有未加载的方法,普通类有无间接或直接继承基础父类:Object等;第三、字节码验证,对数据流和控制流进行分析,保证不会做出危害虚拟机的行为,如是否把父类赋值给子类,是否把对象赋值给一个非此类型的对象等;第四、符号引用验证,主要是类、变量、方法描述是否能找的到,如全限定名是否能找到该文件,是否具有可访问性等,主要对内部结构的判定。

3、准备 不会为实例变量赋值,主要为类静态变量赋初值,通常为0值如static int a=123此时a=0,final int b=123此时b=123;

4、解析 将常量池中的符号引用转化为直接引用的过程。这里说的符号引用指变量类型,直接引用指可以直接定位到对象的句柄。类、方法、字段、接口解析,根据全限定名获得相关对象,拿到它的类型,若无对所在类访问权会抛出IllegalAccessError,无字段NoSuchFieldError,无方法NoSuchMethodError,是类不是接口会抛出IncompatibleClassChangeError

5、初始化 根据程序要求加载类和必要的资源。有且仅有四种情况,需要主动初始化后才能执行接下来的操作 ,所以要先执行上面的四步。第一、new对象或static标记的类、方法、变量;第二、继承的父类,子类如要执行就需要初始化父类;第三、反射类里的方法,那肯定要初始化了;第四、执行的主类,用main方法的类。其他被动初始化的情况不需要考虑。

其实这一条还能衍生出一个问题:如何快速实现应用加载,就需要尽量避免上述行为。

小例子:


public class SuperClass {

 static {

  System.out.println("SuperClass!!");

 }

 public static int value = 1;

}

public class SubClass extends SuperClass {

 static {

  System.out.println("SubClass!!");

 }

}

public class TestClassLoad {


 public static void main(String[] args) {

  System.out.println(SubClass.value);


  SuperClass superClass = new SubClass();

 }

}


SuperClass!!

1

SubClass!!

执行结果说明一个问题:子类调用父类变量的时候,子类没有初始化,因为此时的代码关系跟子类无关;子类初始化的时候,父类也没有再初始化,因为父类在当前方法体中已经初始化过了。接口与父类的唯一区别在于,接口初始化不会要求父接口,只有用到父接口才会初始化,同样的都会生成<clinit>类构造器。

这个时候加载类构造器<clinit>,会初始化类中所有变量,当然父类先于子类初始化

6、使用 加载完之后,该怎么样调用怎么样调用,TextView设置文字,ImageView设置图片等等

7、卸载  类不再被调用,如类被GC回收,虚拟机退出。


两个类是否相等,主要在于第一使用同一个加载器加载,第二全限定名地址一致


为什么要提出上面的问题呢?接下来要讲讲虚拟机的一个加载机制。

在虚拟机的角度来看,有两种类加载器,一种叫系统加载器(Bootstrap ClassLoader),一种叫自定义加载器(extends ClassLoader),这种呢又分为两个,一种叫应用加载器,一种叫扩展类加载器,一般默认为前者;而我们的应用程序加载主要由上面三个加载器相互配合完成的。三者的关系如Application-->Extension-->Bootsrap,双亲委派机制是指两两以组合的方式,子加载器先去调用父加载器的方法,没找到目标对象再去用子加载器

伪代码如下:

loadClass(String name,boolean resolve){

Class c=findLoadedClass()

if(c==null){

try{

if(parent !=null)

c=parent.loadClass(name,false);

else

c=findBootstrapClassOrNull(name);

}catch(ClassNotFoundException e){ }

}

if(c==null)

c=findClass(name);

}

Java提倡我们去把自己调用类的逻辑写在findClass里,这样有助于双亲委派机制的正常使用。

破坏1、重写loadClass

破坏2、使用线程上下文加载器去让父加载器去调用子加载器的方法

破坏3、热加载 现在常用的做法是自定义类加载器并将原bug模块覆盖-OSGI

但由于自定义加载器之间的规则如果混乱,出现同时互相引用的问题,那么会最终找不到类,而出现线程死锁和内存泄露的问题。

关于热修复更多:http://blog.csdn.net/reboot123/article/details/53641127

下一节我们会讨论一下线程并发的问题。


目录
相关文章
|
1月前
|
存储 Java 计算机视觉
Java代码居然可以做出如此高级的图片编辑系统
Java代码居然可以做出如此高级的图片编辑系统
27 0
|
1月前
|
前端开发 Java API
类加载器“如果我定义了一个类名与Java核心类类名相同,那它还能被加载吗?”
类加载器“如果我定义了一个类名与Java核心类类名相同,那它还能被加载吗?”
|
1月前
|
存储 Java 数据安全/隐私保护
【JVM】Java虚拟机栈(Java Virtual Machine Stacks)
【JVM】Java虚拟机栈(Java Virtual Machine Stacks)
35 0
|
20天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
60 0
|
1月前
|
Java 编译器 程序员
Java中的异常处理:从基础到高级
【2月更文挑战第24天】本文将深入探讨Java中的异常处理,从基础的try-catch块到高级的异常处理策略。我们将了解如何使用Java的异常处理机制来提高代码的健壮性和可维护性,以及如何处理运行时和编译时的异常。
22 0
|
28天前
|
并行计算 安全 Java
深入理解Java并发编程:从基础到高级
【2月更文挑战第30天】 本文将深入探讨Java并发编程的核心概念和技术,包括线程、锁、同步、并发集合等。我们将从基础知识开始,逐步深入到高级主题,如Fork/Join框架、CompletableFuture和反应式编程。通过本文,你将能够理解并发编程的重要性,掌握Java中实现高效并发的关键技术和方法。
|
1月前
|
存储 Java 开发者
深入理解Java虚拟机(JVM)内存管理
【2月更文挑战第11天】 在本篇文章中,我们将深入探讨Java虚拟机(JVM)的内存管理机制,一项对于优化Java应用性能至关重要的技术领域。不同于常规的技术文章摘要,我们不仅概述了JVM内存管理的基本概念,还将引导读者通过实际案例理解其在现实世界应用中的重要性。从堆(Heap)和栈(Stack)的区别开始,到垃圾收集(Garbage Collection)机制的工作原理,本文旨在为Java开发者提供一个清晰、系统的JVM内存管理知识框架,帮助他们在开发过程中做出更加明智的决策。
|
2月前
|
存储 算法 Java
Java虚拟机内存管理机制
【2月更文挑战第7天】本文主要介绍了Java虚拟机内存管理机制的基本原理和实现方式。Java虚拟机的内存管理机制是Java程序运行的重要组成部分,对程序性能和稳定性有着直接的影响。文章首先从Java虚拟机内存模型入手,介绍了Java虚拟机中堆内存、方法区、栈、PC寄存器等内存区域的功能特点和使用方式;然后详细阐述了Java虚拟机内存管理机制的垃圾回收算法和回收器的分类、优化和实现过程;最后介绍了一些常见的内存问题和优化技巧,以及如何通过代码调优和合理使用内存配置参数来提高程序的性能和稳定性。
|
9天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
10天前
|
安全 Java 开发者
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第9天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细解析Java中的同步机制,包括synchronized关键字、Lock接口以及并发集合等,并探讨它们如何影响程序的性能。此外,我们还将讨论Java内存模型,以及它如何影响并发程序的行为。最后,我们将提供一些实用的并发编程技巧和最佳实践,帮助开发者编写出既线程安全又高效的Java程序。
22 3

热门文章

最新文章