JVM虚拟机-类加载器子系统
转自博客:http://www.cnblogs.com/muffe/p/3541189.html 还有一些自己补充的知识点
一、类加载器基本概念
顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。但第二次实例化一个类时,就从对应Class类newInstance(),不用每次都读取.class文件。
二、类加载过程
一、JVM将整个类加载过程划分为了三个步骤:
(1)装载(加载)
装载过程负责找到二进制字节码并加载至JVM中,JVM通过类名、类所在的包名通过ClassLoader来完成类的加载,同样,也采用以上三个元素来标识一个被加载了的类:类名+包名+ClassLoader实例ID,因此不同类加载器加载相同的类是不同的。有继承,将先在加载父类。
将类.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区中的数据结构
(2)链接
链接过程负责对二进制字节码的格式进行:校验、解析类中调用的接口、类。校验是防止不合法的.class文件,然后 对类中的所有属性、调用方法进行解析,以确保其需要调用的属性、方法存在,以及具备应的权限(例如public、private域权限等),会造成NoSuchMethodError、NoSuchFieldError等错误信息。
连接:
a、验证:确保被加载的类的正确性
b、准备:为类的静态变量分配内存,并将其初始化为默认值
c、解析: 把类中的符号引用转化为直接引用
(3)初始化
初始化过程即为执行类中的静态初始化代码、构造器代码以及静态属性的初始化。
在四种情况下初始化过程会被触发执行:
调用了new;
反射调用了类中的方法;
子类调用了初始化(先执行父类静态代码和静态成员,再执行子类静态代码和静态变量,然后调用父类构造器,最后调用自身构造器。);
JVM启动过程中指定的初始化类。
三、类加载器的代理模式(双亲委派模型)
类加载器在尝试自己去查找某个类的字节代码并定义它时,会先代理给其父类加载器,由父类加载器先去尝试加载这个类,依次类推。
具体过程详见《http://baike.baidu.com/link?url=AN43X7Jb8MPxU8gX3-I5Twu0-YjqRz--cWMOQjOue3uMAh-8kELZC0pZpBfVTpeuVJ_YtxUczSGcpqDE69yNwq》。类推顺序如下:

注意这不是继承关系,而是代理关系。 主要分为以下几类:
(1) Bootstrap ClassLoader
这是JVM的根ClassLoader,它是用C++实现的,JVM启动时初始化此ClassLoader,并由此ClassLoader完成$JAVA_HOME中jre/lib/rt.jar(Sun JDK的实现)中所有class文件的加载,这个jar中包含了java规范定义的所有接口以及实现。
(2) Extension ClassLoader
JVM用此classloader来加载扩展功能的一些jar包
(3) System ClassLoader或者AppClassLoader
JVM用此classloader来加载启动参数中指定的Classpath中的jar包以及目录,在Sun JDK中ClassLoader对应的类名为AppClassLoader。
(4) User-Defined ClassLoader
User-DefinedClassLoader是Java开发人员继承ClassLoader抽象类自行实现的ClassLoader,基于自定义的ClassLoader可用于加载非Classpath中的jar以及目录
注意:
1、所有的类加载器都继承与ClassLoader类。并且BootstrapClassLoader、ExtClassLoader、AppClassLoader继承于Java.net.URLClassLoader,可以从本地和网上下载字节码。URLClassLoader继承ClassLoader。;
2、BootstrapClassLoader是最先加载的,它然后依次加载出ExtClassLoader、AppClassLoader对象。
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);
}
}
四、加载.class文件的方式
1、从本地内存系统中直接加载
2、通过网络下载.class文件
3、子类调用了初始化(父类静态代码>子类静态代码>父类构造器>子类构造器)
4、JVM启动过程中指定的初始化类
五、Class类
Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。
1、调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如:
MyObject x;
Class c1 = x.getClass();
2、使用Class类的中静态forName()方法获得与字符串对应的Class对象。例如:
Class c2=Class.forName("MyObject"),Employee必须是接口或者类的名字。
3、获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配的类对象。例如
Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;
注意:Class对象实际上描述的只是类型,而这类型未必是类或者接口。例如上面的int.class是一个Class类型的对象。由于历史原因,数组类型的getName方法会返回奇怪的名字。
1、getName()
一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:
x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。
返回该类的类加载器。
返回表示数组组件类型的 Class。
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
判定此 Class 对象是否表示一个数组类。
1、forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象。例如
Object obj = Class.forName(s).newInstance();
if(e.getClass() == Employee.class)...
JVM虚拟机-类加载器子系统的更多相关文章
- Java JVM——2.类加载器子系统
概述 类加载器子系统在Java JVM中的位置 类加载器子系统的具体实现 类加载器子系统的作用 ① 负责从文件系统或者网络中加载.class文件,Class 文件在文件开头有特定的文件标识. ② Cl ...
- JVM之类加载器子系统
类加载器子系统 作用 负责从文件系统或网络系统中加载class文件,class文件在开头有特殊的标记(魔术开头CA FE BA BE) ClassLoader只负责加载class文件,至于能否运行,由 ...
- java jvm虚拟机类加载器
在Java中任意一个类都是由这个类本身和加载这个类的类加载器来确定这个类在JVM中的唯一性. 类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到J ...
- JVM详解(二)-- 第2章 类加载器子系统
一.JVM内存结构 1.1 内存结构---概略图 1.2 内存结构--详细图 二.类加载器子系统的作用 类加载器子系统负责从文件系统或网络中加载.Class文件,文件需要有特定的标识(cafe bab ...
- JVM之类加载器、加载过程及双亲委派机制
JVM 的生命周期 虚拟机的启动 Java 虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实 ...
- JVM(一)类加载器与类加载过程
JVM是面试必面的一个知识点,也是高级程序员必备的一个技能.以下是JVM整体核心内容,包括类加载系统,运行时数据区内部结构,执行引擎,本地方法接口. 首先来学习类的加载器,虚拟机把描述类的数据从Cla ...
- JVM自定义类加载器加载指定classPath下的所有class及jar
一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责 ...
- Java虚拟机类加载器及双亲委派机制
所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...
- 【深入理解JVM】类加载器与双亲委派模型 (转)
出处: [深入理解JVM]类加载器与双亲委派模型 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过 ...
随机推荐
- 继承 (js原型链)
原型链是实现继承的主要方法.基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法. 1.构造函数.原型.实例的关系: 每个构造函数都有原型属性(Prototype),指向一个原型对象(函数创 ...
- 大数乘法java版
import java.util.*; import java.math.*; public class NumMul{ public static void main(String args[]){ ...
- java.lang.NoClassDefFoundError: org/apache/ibatis/cursor/Cursor
因为mybatis的版本和mybatis-spring的版本不兼容导致的,解决方法:mybatis的3.4.0及以上版本用mybatis-spring1.3.0及以上版本:mybatis的3.4.0以 ...
- DIOCP组件(Delphi IOCP)代码阅读之ADO内存表
DIOCP组件(Delphi IOCP)代码阅读之ADO内存表 代码中有 class procedure TADOTools.loadFromStream(pvDataSet: TCustomADOD ...
- 谁说delphi没有IOCP库,delphi新的IOCP类库,开源中: DIOCP组件JSON流模块说明
单元:JSonStream.pas 简介:本单元实现 流和json对象的相互转换,其中有一些保留的key. 依赖:superobject 保留key: __result.errCode 返回的错误编 ...
- 判断\r\n结束标准
ucPrev==0x0D&&ucCur==0x0A \r\n uint8_t ucPrev =0,ucCur = 0; uint32_t recvlen = 0; for (; uiL ...
- Intellij idea 系列教程之破解方法
Intellij idea 系列教程之破解方法 Intellij idea 系列教程目录(https://www.cnblogs.com/binarylei/p/10347600.html) 到这个地 ...
- Activiti 5.18启动流程到完成所有任务之间的数据库变化(转)
来写一下Activiti 5.18版本从启动流程到整个流程结束之间数据库表的变化 先给出流程图,很简单的流程,就是两个UserTask: 代码如下: DeploymentBuilder builder ...
- python之函数篇3
一:函数的定义 1)函数的简单使用,无参函数 def f1(): # 定义函数指定函数名 print("hello") # 指定功能 f1() # 调用函数,才能执行函数体里面的功 ...
- SQL语句备份和还原数据库
1,使用SQL最简单备份,还原数据库 1 /* 备份 */ 2 backup database Test to disk='D:/Test.bak' 3 /* 还原 */ 4 restore data ...