`
greemranqq
  • 浏览: 975734 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

JVM 类加载器介绍

    博客分类:
  • JVM
阅读更多

 通过一个类的全限定名来获取描述此类的二进制字节流,这个动作放到虚拟机外部去实现,以便让程序自己决定如何去获取所需要的类。这个模块的动作成为“类加载器”。
        唯一性:对于任意一个类,必须类的加载器和类本身,同时来确立其唯一性,每一个类加载器,都拥有一个独立的类的名称空间。
 比较两个类是否相等,只有在两个类是由同一个类加载器加载的前提下才有意义,否则即使两个类来源于同一个class 文件,被同一个虚拟机加载,只要加载器不同,那么他们两个类必定不同。这里的“相等”包括对象的equals(),isAssignableForm(),isInstance 方法的返回结果。可以代码简单演示:

public class ClassLoaderTest {
 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
 ClassLoader myLoder = new ClassLoader() {
  @Override
  public Class<?> loadClass(String name) throws ClassNotFoundException {
  String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
  InputStream in = getClass().getResourceAsStream(fileName);
    Class<?> c = null;
    try {
     if(in == null){
      return super.loadClass(name);
     }
     byte[] b = new byte[in.available()];
     in.read(b);
     c = defineClass(name, b, 0, b.length);
    } catch (Exception e) {
     e.printStackTrace();
    }
    return c;
   }
  };
  Object obj = myLoder.loadClass("com.ClassLoaderTest").newInstance();
  System.out.println(obj.getClass());
  System.out.println(obj instanceof com.ClassLoaderTest);
 }
}

 结果:
class com.ClassLoaderTest
false

返回false 是因为系统存在两个ClassLoaderTest,一个是系统默认加载的,一个是自己new 的加载器,虽然是用一个class 文件,但是依然是独立的两个类。而我们经常做equals判断的时候会先进行instanceof 检查,大多数情况都是true,因为统一是默认的加载器加载的,下面看看一些加载器的工作情况。

一、双亲委派模型
 从JAVA虚拟机的角度来说,主要有两个加载器:一种是启动了加载器
(Bootstrap ClassLoader),这是由C++写的,是虚拟机一部分,另一种是其他类的加载器,是有Java实现的,独立于虚拟机外,并且都继承自抽象类java.lang.ClassLoader.细分一下,可以分为扩展类加载器(Extension ClassLoader)和应用程序加载器(Application ClassLoader)。

        1.启动类加载器:主要负责加载<JAVA_HOME>\lib 目录中的,虚拟机能识别的文件名的文件。这个加载器无法没Java程序直接用。
 2.扩展类加载器:主要负责加载<JAVA_HOME>\lib\ext下的,或者被java.ext.dirs 系统变量指定的类库,开发者可以直接使用的。
 3.应用类加载器:主要负责加载用户类路径(classpath)上所指定的类库,程序中默认的类加载器,开发者可以自己进行使用。
 这几个加载器在rt.jar sun.misc.Launcher 下,这里我还进不去..!他们直接由上到下的关系,就是双亲委派模型,关于这个模型定义,这里大概介绍一下,它要求除了启动类加载器以外,其他都需要自己的父类加载器,并且父子关系不是继承,而是组合,也就是说类的加载会先让最上面的进行加载,加载不了的,再让后面的进行加载,你会发现每次都会从启动类加载器开始,而且object 这个最大的父类就在rt.jar 里面,也是有启动类加载器进行加载的。这种模式是JDK推荐的,因为如果不按这种方式,自己写个Object 类,自己定义的位置进行加载,那么会混乱。
 对于双亲委派模型代码都集中在java.lang.ClassLoader 的loadClass 中,可以通过图和源码进行了解:
图参考:http://yueyemaitian.blog.163.com/blog/static/2165043320097211052534/

 

  

protected synchronized Class<?> loadClass(String name, boolean resolve)
 throws ClassNotFoundException
    {
 //1.  先检查是否被加载过了
 Class c = findLoadedClass(name);
 if (c == null) {
     try {
  if (parent != null) {
      c = parent.loadClass(name, false);
  } else {
      c = findBootstrapClass0(name);
  }
     } catch (ClassNotFoundException e) {
         // 2. 如果父类找不到,就抛出ClassNotFoundException
  // 默认直接抛出异常,JDK要求重写这个方法
         c = findClass(name);
     }
 }
 if (resolve) {
     resolveClass(c);
 }
 return c;
    }  

  

注:JDK 建议我们在实现自己的加载器的时候,不要覆盖locaClass方法,而是建议我们去重写findClass 方法,这样能保证双亲委派模型,同时也实现了自己的方法。

           双亲委派模型比较稳定,能很好的解决类加载的基础类问题(越基础的类,越由上层加载器进行记载),这些了之所以叫"基础",因为他们总是被用户代码调用API,但是在某些时候,这些基础类又要会调回用户代码,怎么办呢?
           比如:用户调用基础类的method-1 方法,而该方法又要调用用户自己写的method-2,这类引用场景一般会在API写了接口,或者一种实现方法,而我们调的时候需要实现自己的方法,比如JDBC,JDNI,提供了接口,具体的实现需要各个不同的数据库厂商去实现,这里就是不基本的双亲委派模型了。
           JNDI现在放在rt.jar 里面,目的是对资源进行查找和集中管理,他需要独立厂商去实现并部署,而启动类加载器不识别这些代码,怎么办呢?
           Java 团队又设计了一个上下文类加载器(Thread Context ClassLoader),可以通过java.lang.Thread 的setContextClassLoder 进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果程序全局都没设置过,那么默认还是App应用程序加载器。
           有了线程上下文加载器,就能加载厂商独立实现的代码了,也就是父类加载器请求子类加载器去完成类的加载动作,双亲委派模型是父类先加载,加载不了再给子类加载,而这里是父类直接请求子类加载,已经破坏了委派模型层次。其中JCE、JAXB、JBI都也都采用了。

           其次,用户在追求程序动态性的时候,希望程序想USB 接口一样,可以不用重启电脑,而更换各种外接东西。为了完成这个诱人的操作,比如OSGI实现了模块化热部署,它的关键是自己定义类加载器的实现机制,每一个模块都有自己的类加载器,需要更换模块的时候,就把模块和类加载器一起换掉,实现热替换。(ps:这玩意儿我也没用过,感觉就像webservice 远程调用那样,规定了接口,客户端固定,然后可以随意的替换服务端,从而客户端获得不同的输出)

           关于osgi 的原理以及机制,可以参考<深入理解osgi>..之类的书。

小结:
 1.这里主要介绍了类加载器的种类以及运行原理,方便我们加深对类的理解
 2.这些都参考JVM里面的东西,写成小章节,方便自己理解,也分享一部分经验。

 

 

 

分享到:
评论

相关推荐

    JVM类加载器说明文档

    总结,Java 类加载器是JVM中的重要组成部分,它决定了类的加载过程和加载源,双亲委派机制保证了类加载的有序性和安全性。理解类加载器的工作原理有助于我们更好地进行程序设计和优化,特别是在开发插件系统、模块化...

    JVM实战-JVM类加载机制案例分析

    2. **类加载器及类加载器的委托机制**:JVM中有三种内置的类加载器,分别是启动类加载器、扩展类加载器和应用类加载器。此外,还可以自定义类加载器。类加载器之间遵循委托机制,即下级类加载器先请求上级类加载器...

    JVM类加载机制详细讲解

    例如,当我们尝试加载 `java.lang.Object` 类时,首先会由启动类加载器加载,如果它找不到,会继续交给扩展类加载器,接着是系统类加载器,最后才会由用户自定义的类加载器尝试加载。 1.3 类加载双亲委派示例 为了...

    深入Java虚拟机_002_深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器

    本部分我们将深入探讨JVM中的类加载器,特别是根类加载器、扩展类加载器和系统类加载器。 首先,让我们了解类加载的基本过程。当JVM启动时,会触发类加载。这个过程分为三个阶段:加载、链接和初始化。加载阶段,类...

    JVM类加载过程.pptx

    Java代码执行流程是JVM的核心流程之一,它首先通过编译器把Java代码转换成字节码,然后通过类加载器加载到内存中,并将其放在运行时数据区的方法区内。最后,执行引擎将字节码翻译成底层系统指令,再交由CPU去执行。

    JVM类加载器 test

    JVM类加载器 test

    JVM类加载分析

    类加载器是JVM实现动态加载的核心组件,它的主要任务是根据类名找到对应的.class文件,并将其转换为内存中的Class对象。Java中的类加载器主要有以下几种: 1. Bootstrap ClassLoader:引导类加载器,负责加载JRE...

    JVM类加载跟踪器

    JVM类加载跟踪器,用于排查jar包冲突、类冲突、类版本冲突、NoClassDefFoundError、ClassNotFoundException 等等类加载相关问题的辅助工具

    JVM:类加载器子系统.pdf

    Java虚拟机(JVM)的类加载器子系统是Java运行时环境的一个重要组成部分,它负责将.class文件加载到内存中,并生成对应的Java类对象。这一过程涵盖了从文件系统或网络获取.class文件、验证类文件的正确性、准备类...

    JVM、Tomcat、OSGI等类加载器整理文档

    在Java世界中,类加载器(ClassLoader)是关键组件,它们负责将类的字节码加载到Java虚拟机(JVM)中。JVM、OSGI(Open Service Gateway Initiative)和Tomcat等容器都涉及到了类加载器的概念,理解它们的工作原理对...

    类加载器文件

    - **直接引用**: 当一个类直接引用另一个类时(例如,类A引用类B),JVM会使用加载类A的类加载器来加载类B。 - **反射调用**: 使用`Class.forName()`方法也会触发类的加载。 - **初始化**: 当类的静态块或静态成员被...

    从JDK源码级别剖析JVM类加载机制

    JVM使用类加载器(ClassLoader)来完成这一任务。在Java中,每个类都由一个对应的ClassLoader实例负责加载。默认的类加载器包括Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和...

    java类加载器

    在Java中,类加载器(Class Loader)是一项核心机制,用于将字节码(.class文件)加载到JVM中,使其成为运行时的对象。类加载器不仅实现了类的加载功能,还确保了Java程序在多线程环境中的安全性和隔离性。类加载器...

    Java虚拟机JVM类加载初始化

    这些内置的类加载器加载的类在JVM生命周期中不会被卸载。而用户自定义的类加载器加载的类,当它们的`Class`对象不再被引用时,可能会被卸载,以节省内存资源。 了解类加载机制对于优化性能、理解和解决类加载相关...

    类加载器(java)

    Java中的类加载器是JVM(Java虚拟机)的核心组件之一,它们负责将.java源代码编译成的.class字节码文件加载到JVM中,从而使得程序能够运行。类加载器不仅涉及到程序的正常执行,还与Java的动态加载、模块化系统以及...

    jvm 加载class文件

    通过对Java中JVM加载`.class`文件的过程及其类加载器的具体工作原理的介绍,我们可以更加深刻地理解Java程序的运行机制。了解这些基础知识对于开发高质量的Java应用程序至关重要。通过掌握类加载器的工作方式,...

    深入Java虚拟机JVM类加载学习笔记

    在Java虚拟机(JVM)中,类加载器(ClassLoader)是负责将类的`.class`文件加载到内存中的重要组件。理解类加载器的工作原理对于深入掌握JVM以及解决实际开发中的问题至关重要。 **1.1 类加载器分类** 类加载器可以...

    性能调优专题-jvm类加载机制-performance-jvmclassloader.zip

    JVM的垃圾收集机制可以回收不再使用的对象,但类加载器却难以卸载。这是因为类加载器与类的关系是“父子关系”,而非“拥有关系”,只有当类加载器被回收,它所加载的类才会一同卸载。 6. **类加载器优化** 优化...

    Java类加载器原理

    Java 类加载器是Java虚拟机(JVM)的核心组成部分,它负责将类的字节码加载到内存中并转换为可执行的Java类。类加载器的作用不仅仅是加载类,还包括确保类的唯一性,避免重复加载,并且遵循特定的加载顺序。以下是对...

Global site tag (gtag.js) - Google Analytics