转自博客: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对象。

  1. public abstract class ClassLoader {
  2. // The parent class loader for delegation
  3. private final ClassLoader parent;
  4.  
  5. public Class<?> loadClass(String name) throws ClassNotFoundException {
  6. return loadClass(name, false);
  7. }
  8.  
  9. protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
  10. synchronized (getClassLoadingLock(name)) {
  11. // First, check if the class has already been loaded
  12. Class<?> c = findLoadedClass(name);
  13. if (c == null) {
  14. try {
  15. if (parent != null) {
  16. c = parent.loadClass(name, false);
  17. } else {
  18. c = findBootstrapClassOrNull(name);
  19. }
  20. } catch (ClassNotFoundException e) {
  21. // ClassNotFoundException thrown if class not found
  22. // from the non-null parent class loader
  23. }
  24.  
  25. if (c == null) {
  26. // If still not found, then invoke findClass in order
  27. // to find the class.
  28. c = findClass(name);
  29. }
  30. }
  31. if (resolve) {
  32. resolveClass(c);
  33. }
  34. return c;
  35. }
  36. }
  37.  
  38. protected Class<?> findClass(String name) throws ClassNotFoundException {
  39. throw new ClassNotFoundException(name);
  40. }
  41. }

四、加载.class文件的方式

  1、从本地内存系统中直接加载

  2、通过网络下载.class文件

  3、子类调用了初始化(父类静态代码>子类静态代码>父类构造器>子类构造器)

  4、JVM启动过程中指定的初始化类

五、Class类

Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
      Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。

(一) 如何得到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方法会返回奇怪的名字。

(二) Class类的常用方法
    1、getName() 
    一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

    2、newInstance()
    Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:
    x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。

    3、getClassLoader() 
    返回该类的类加载器。

    4、getComponentType() 
    返回表示数组组件类型的 Class。

    5、getSuperclass() 
    返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。

    6、isArray() 
    判定此 Class 对象是否表示一个数组类。

(三) Class的一些使用技巧
    1、forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象。例如
    Object obj = Class.forName(s).newInstance();

    2、虚拟机为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。例如:
    if(e.getClass() == Employee.class)...
(四)Class的详细方法 
 

JVM虚拟机-类加载器子系统的更多相关文章

  1. Java JVM——2.类加载器子系统

    概述 类加载器子系统在Java JVM中的位置 类加载器子系统的具体实现 类加载器子系统的作用 ① 负责从文件系统或者网络中加载.class文件,Class 文件在文件开头有特定的文件标识. ② Cl ...

  2. JVM之类加载器子系统

    类加载器子系统 作用 负责从文件系统或网络系统中加载class文件,class文件在开头有特殊的标记(魔术开头CA FE BA BE) ClassLoader只负责加载class文件,至于能否运行,由 ...

  3. java jvm虚拟机类加载器

    在Java中任意一个类都是由这个类本身和加载这个类的类加载器来确定这个类在JVM中的唯一性. 类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到J ...

  4. JVM详解(二)-- 第2章 类加载器子系统

    一.JVM内存结构 1.1 内存结构---概略图 1.2 内存结构--详细图 二.类加载器子系统的作用 类加载器子系统负责从文件系统或网络中加载.Class文件,文件需要有特定的标识(cafe bab ...

  5. JVM之类加载器、加载过程及双亲委派机制

    JVM 的生命周期 虚拟机的启动 Java 虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实 ...

  6. JVM(一)类加载器与类加载过程

    JVM是面试必面的一个知识点,也是高级程序员必备的一个技能.以下是JVM整体核心内容,包括类加载系统,运行时数据区内部结构,执行引擎,本地方法接口. 首先来学习类的加载器,虚拟机把描述类的数据从Cla ...

  7. JVM自定义类加载器加载指定classPath下的所有class及jar

    一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责 ...

  8. Java虚拟机类加载器及双亲委派机制

    所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...

  9. 【深入理解JVM】类加载器与双亲委派模型 (转)

    出处: [深入理解JVM]类加载器与双亲委派模型 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过 ...

随机推荐

  1. 使用Visual VM 查看linux中tomcat运行时JVM内存

    前言:在生产环境中经常发生服务器内存溢出,假死或者线程死锁等异常,导致服务不可用.我们经常使用的解决方法是通过分析错误日记,然后去寻找代码到底哪里出现了问题,这样的方式也许会奏效,但是排查起来耗费时间 ...

  2. Activity2.java

    package com.hanqi.text3; import android.app.Activity; import android.os.Bundle; import android.os.Pe ...

  3. poj 1182 (关系并查集) 食物链

    题目传送门:http://poj.org/problem?id=1182 这是一道关系型并查集的题,对于每个动物来说,只有三种情况:同类,吃与被吃: 所以可以用0,1,2三个数字代表三种情况,在使用并 ...

  4. javascript 高级程序设计 六

    上一节还有一个注意的地方:建议所有函数的必需参数使用命名参数,而非必须的参数使用对象来封装. 通过这几天的读书,发现了一个深入了解所学知识的一个捷径——读书.本来我在计算机这方法的所有知识一般都是从视 ...

  5. C#泛型的学习

    编码: class Program { static void Main(string[] args) { ; Test<int> test1 = new Test<int>( ...

  6. 单细胞RNA测序技术之入门指南

    单细胞RNA测序技术之入门指南 [字体: 大 中 小 ] 时间:2018年09月12日 来源:生物通   编辑推荐: 在这个飞速发展的测序时代,DNA和RNA测序已经逐渐成为“实验室中的家常菜”.若要 ...

  7. db2创建数据库

    1.在实例用户用户下执行 db2 create database <DBName>  on /home/db2inst1/<DBName>  using codeset UTF ...

  8. PHP数组对象互转

    //数组转对象 function array2object($array) { if (is_array($array)) { $obj = new StdClass(); foreach ($arr ...

  9. SVN 钩子 同步测试服务器

    http://blog.csdn.net/showso2006/article/details/6750441 多人开始使用subversion之后,就想着,要建立一个测试用的服务器,不需要把文件up ...

  10. Android资源相关语法

    2018-08-29 getResources().getString(Rid)获取配置中的字符串