`

Java Classloading Mechanism : ClassLoader & ASM & 动态字节码增强

阅读更多
Setting the class path:
http://docs.oracle.com/javase/7/docs/technotes/tools/findingclasses.html
引用
The default class path is the current directory. Setting the CLASSPATH variable or using the -classpath command-line option overrides that default, so if you want to include the current directory in the search path, you must include "." in the new settings.



ClassLoader装载一个类时:
自底向上检查是否已装载 - 过程中的每层:在本层cache中发现已装载,则返回这个已装载的类实例,调用结束;发现未加载,继续委托上层。
若直至最顶层都未发现该类的已装载实例
自顶向下尝试装载 - 过程中的每层:经搜索本层path后装载类成功,则返回这个装载成功的类实例,调用结束;装载未成功,将ClassNotFoundException抛给下层,委托下层继续尝试装载。
若直至最底层都未装载成功
则抛给应用一个ClassNotFoundException。


Java Class Loading:
http://www.techjava.de/topics/2008/01/java-class-loading/
引用
The loading of Java classes is performed by class loaders (CL), they are responsible for loading classes into the JVM. Simple applications can use the Java platform’s built-in class loading facility to load their classes, more complex applications tend to define their own custom class loaders.

The class loaders in Java are organized in a tree. By request a class loader determines if the class has already been loaded in the past, looking up in its own cache. If the class is present in the cache the CL returns the class, if not, it delegates the request to the parent. If the parent is not set (is Null) or can not load the class and throws a ClassNotFoundException the classloader tries to load the class itself and searches its own path for the class file. If the class can be loaded it is returned, otherwise a ClassNotFoundException is thrown. The cache lookup goes on recursively from child to parent, until the tree root is reached or a class is found in cache. If the root is reached the class loaders try to load the class and unfold the recursion from parent to child. Summarizing that we have following order:
  • Cache
  • Parent
  • Self
This mechanism ensures that classes tending to be loaded by class loaders nearest to the root. Remember, that parent class loader is always has the opportunity to load a class first. It is important to ensure that core Java classes are loaded by the bootstrap loader, which guarantees that the correct versions of classes such as java.lang.Object are loaded. Furthermore it ensures, that one class loader sees only classes loaded by itself or its parent (or further ancestors) and it cannot see classes loaded by its children or siblings!


The picture illustrates the hierarchy of class loaders. Root loader is bootstrap class loader which has native implementation and cannot be instantiated by Java code.




The Java Tutorials -> Understanding Extension Class Loading:
http://download.oracle.com/javase/tutorial/ext/basics/load.html
引用
When the runtime environment needs to load a new class for an application, it looks for the class in the following locations, in order:
1 Bootstrap classes: the runtime classes in rt.jar, internationalization classes in i18n.jar, and others.
2 Installed extensions: classes in JAR files in the lib/ext directory of the JRE, and in the system-wide, platform-specific extension directory (such as /usr/jdk/packages/lib/ext on the SolarisTM Operating System, but note that use of this directory applies only to JavaTM 6 and later).
3 The class path: classes, including classes in JAR files, on paths specified by the system property java.class.path. If a JAR file on the class path has a manifest with the Class-Path attribute, JAR files specified by the Class-Path attribute will be searched also. By default, the java.class.path property's value is ., the current directory. You can change the value by using the -classpath or -cp command-line options, or setting the CLASSPATH environment variable. The command-line options override the setting of the CLASSPATH environment variable.

The precedence list tells you, for example, that the class path is searched only if a class to be loaded hasn't been found among the classes in rt.jar, i18n.jar or the installed extensions.

Unless your software instantiates its own class loaders for special purposes, you don't really need to know much more than to keep this precedence list in mind. In particular, you should be aware of any class name conflicts that might be present. For example, if you list a class on the class path, you'll get unexpected results if the runtime environment instead loads another class of the same name that it found in an installed extension.


The Java Class Loading Mechanism:
The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a "parent" class loader. When loading a class, a class loader first "delegates" the search for the class to its parent class loader before attempting to find the class itself.

Here are some highlights of the class-loading API:
  • Constructors in java.lang.ClassLoader and its subclasses allow you to specify a parent when you instantiate a new class loader. If you don't explicitly specify a parent, the virtual machine's system class loader will be assigned as the default parent.
  • The loadClass method in ClassLoader performs these tasks, in order, when called to load a class:
  •           1 If a class has already been loaded, it returns it.
              2 Otherwise, it delegates the search for the new class to the parent class loader.
              3 If the parent class loader does not find the class, loadClass calls the method findClass to find and load the class.
  • The findClass method of ClassLoader searches for the class in the current class loader if the class wasn't found by the parent class loader. You will probably want to override this method when you instantiate a class loader subclass in your application.
  • The class java.net.URLClassLoader serves as the basic class loader for extensions and other JAR files, overriding the findClass method of java.lang.ClassLoader to search one or more specified URLs for classes and resources.




Java Security Architecture -> 5 Secure Class Loading:
http://download.oracle.com/javase/1.4.2/docs/guide/security/spec/security-spec.doc5.html
引用
5.1 Class Loader Class Hierarchies
When loading a class, because there can be multiple instances of class loader objects in one Java Virtual Machine, an important question is how do we determine which class loader to use.

5.2 The Primordial Class Loader
Because each class is loaded by its class loader, and each class loader itself is a class and must be loaded by another class loader, we seem to have the obvious chicken-and-egg problem, i.e., where does the first class loader come from? There is a "primordial'' class loader that bootstraps the class loading process. The primordial class loader is generally written in a native language, such as C, and does not manifest itself within the Java context. The primordial class loader often loads classes from the local file system in a platform-dependent manner.

Some classes, such as those defined in the java.* package, are essential for the correct functioning of the Java Virtual Machine and runtime system. They are often referred to as base classes. Due to historical reasons, all such classes have a class loader that is a null. This null class loader is perhaps the only sign of the existence of a primordial class loader. In fact, it is easier to simply view the null class loader as the primordial class loader.

Given all classes in one Java application environment, we can easily form a class loading tree to reflect the class loading relationship. Each class that is not a class loader is a leaf node. Each class's parent node is its class loader, with the null class loader being the root class. Such a structure is a tree because there cannot be cycles -- a class loader cannot have loaded its own ancestor class loader.


5.3 Class Loader Delegation
When one class loader is asked to load a class, this class loader either loads the class itself or it can ask another class loader to do so. In other words, the first class loader can delegate to the second class loader. The delegation relationship is virtual in the sense that it has nothing to do with which class loader loads which other class loader. Instead, the delegation relationship is formed when class loader objects are created, and in the form of a parent-child relationship. Nevertheless, the system class loader is the delegation root ancestor of all class loaders. Care must be taken to ensure that the delegation relationship does not contain cycles. Otherwise, the delegation process may enter into an infinite loop.

5.4 Class Resolution Algorithm
The default implementation of the Java 2 SDK ClassLoader method for loading a class searches for classes in the following order:
  • Check if the class has already been loaded.
  • If the current class loader has a specified delegation parent, delegate to the parent to try to load this class. If there is no parent, delegate to the primordial class loader.
  • Call a customizable method to find the class elsewhere.

Here, the first step looks into the class loader's local cache (or its functional equivalent, such as a global cache) to see if a loaded class matches the target class. The last step provides a way to customize the mechanism for looking for classes; thus a custom class loader can override this method to specify how a class should be looked up. For example, an applet class loader can override this method to go back to the applet host and try to locate the class file and load it over the network.

If at any step a class is located, it is returned. If the class is not found using the above steps, a ClassNotFound exception is thrown.

Observe that it is critical for type safety that the same class not be loaded more than once by the same class loader. If the class is not among those already loaded, the current class loader attempts to delegate the task to the parent class loader. This can occur recursively. This ensures that the appropriate class loader is used. For example, when locating a system class, the delegation process continues until the system class loader is reached.

We have seen the delegation algorithm earlier. But, given the name of any class, which class loader do we start with in trying to load the class? The rules for determining the class loader are the following:
  • When loading the first class of an application, a new instance of the URLClassLoader is used.
  • When loading the first class of an applet, a new instance of the AppletClassLoader is used.
  • When java.lang.Class.ForName is directly called, the primordial class loader is used.
  • If the request to load a class is triggered by a reference to it from an existing class, the class loader for the existing class is asked to load the class.



Understanding the Java ClassLoader(见PDF附件,务须精读!):
http://www.ibm.com/developerworks/java/tutorials/j-classloader/


Java programming dynamics, Part 1: Java classes and class loading:
http://www.ibm.com/developerworks/java/library/j-dyn0429/
Java programming dynamics系列总共 8 parts,都不错!作者是牛人。读之!



Understanding the Java Classloading Mechanism:
http://www2.sys-con.com/itsg/virtualcd/java/archives/0808/chaudhri/index.html
引用
The smallest unit of execution that gets loaded by a ClassLoader is the Java class file. A class file contains the binary representation of a Java class, which has the executable bytecodes and references to other classes used by that class, including references to classes in the Java API. Stated simply, a ClassLoader locates the bytecodes for a Java class that needs to be loaded, reads the bytecodes, and creates an instance of the java.lang.Class class. This makes the class available to the JVM for execution. Initially when a JVM starts up, nothing is loaded into it. The class file of the program being executed is loaded first and then other classes and interfaces are loaded as they get referenced in the bytecode being executed. The JVM thus exhibits lazy loading, i.e., loading classes only when required, so at start-up the JVM doesn't need to know the classes that would get loaded during runtime. Lazy loading plays a key role in providing dynamic extensibility to the Java platform.

The following is a high-level class-loading algorithm executed by a ClassLoader when a client requests it to load a class:
1.   A check is performed to see if the requested class has already been loaded by the current ClassLoader. If so, the loaded class is returned and the request is completed. The JVM caches all the classes that are loaded by a ClassLoader. A class that has previously been loaded by a ClassLoader is not loaded again.
2.   If the class is not already loaded, the request is delegated to the parent ClassLoader, before the current ClassLoader tries to load it. This delegation can go all the way up to the bootstrap ClassLoader, after which no further delegation is possible.
3.   If a parent fails to return a class because it was unable to load it, the current ClassLoader will then try to search for the requested class. Each ClassLoader has defined locations where it searches for classes to load. For instance, the bootstrap ClassLoader searches in the locations (directories and zip/jar files) specified in the sun.boot.class.path system property. The system ClassLoader searches for classes in the locations specified by the classpath (set as the java.class.path system property) command-line variable passed in when a JVM starts executing. If the class is found, it's loaded into the system and returned, completing the request.
4.   If the class is not found, a java.lang.ClassNotFoundException is thrown.



The basics of Java class loaders:
http://www.javaworld.com/javaworld/jw-10-1996/jw-10-indepth.html


ClassLoader : Java Glossary:
http://mindprod.com/jgloss/classloader.html



http://www.iteye.com/topic/136427




深入探讨 Java 类加载器:
http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html
引用
顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。

基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例。java.lang.ClassLoader 类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class 类的一个实例

除了引导类加载器之外,所有的类加载器都有一个父类加载器。


每个 Java 类(补充:即每个Class实例对象)都维护着一个指向定义它的类加载器的引用,通过 getClassLoader() 方法就可以获取到此引用。

类加载器在尝试自己去查找某个类的字节代码并定义它时,会先代理(注:这里的代理指的是delegate,叫委托更好点)给其父类加载器,由父类加载器先去尝试加载这个类,依次类推。在介绍代理模式背后的动机之前,首先需要说明一下 Java 虚拟机是如何判定两个 Java 类是相同的。Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。比如一个 Java 类 com.example.Sample,编译之后生成了字节代码文件 Sample.class。两个不同的类加载器 ClassLoaderA 和 ClassLoaderB 分别读取了这个 Sample.class 文件,并定义出两个 java.lang.Class 类的实例来表示这个类。这两个实例是不相同的。对于 Java 虚拟机来说,它们是不同的类。试图对这两个类的对象进行相互赋值,会抛出运行时异常 ClassCastException。

代理模式是为了保证 Java 核心库的类型安全。所有 Java 应用都至少需要引用 java.lang.Object 类,也就是说在运行的时候,java.lang.Object 这个类需要被加载到 Java 虚拟机中。如果这个加载过程由 Java 应用自己的类加载器来完成的话,很可能就存在多个版本的 java.lang.Object 类,而且这些类之间是不兼容的。通过代理模式,对于 Java 核心库的类的加载工作由引导类加载器来统一完成,保证了 Java 应用所使用的都是同一个版本的 Java 核心库的类,是互相兼容的。
不同的类加载器为相同名称的类创建了额外的名称空间。相同名称的类可以并存在 Java 虚拟机中,只需要用不同的类加载器来加载它们即可。不同类加载器加载的类之间是不兼容的,这就相当于在 Java 虚拟机内部创建了一个个相互隔离的 Java 类空间。

在前面介绍类加载器的代理模式的时候,提到过类加载器会首先代理给其它类加载器来尝试加载某个类。这就意味着真正完成类的加载工作的类加载器和启动这个加载过程的类加载器,有可能不是同一个。真正完成类的加载工作是通过调用 defineClass 来实现的;而启动类的加载过程是通过调用 loadClass 来实现的。前者称为一个类的定义加载器(defining loader),后者称为初始加载器(initiating loader)。在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。两种类加载器的关联之处在于:一个类的定义加载器是它引用的其它类的初始加载器。如类 com.example.Outer 引用了类 com.example.Inner,则由类 com.example.Outer 的定义加载器负责启动类 com.example.Inner 的加载过程。
方法 loadClass() 抛出的是 java.lang.ClassNotFoundException 异常;方法 defineClass() 抛出的是 java.lang.NoClassDefFoundError 异常。
类加载器在成功加载某个类之后,会把得到的 java.lang.Class 类的实例缓存起来。下次再请求加载该类的时候,类加载器会直接使用缓存的类的实例,而不会尝试再次加载。也就是说,对于一个类加载器实例来说,相同全名的类只加载一次,即 loadClass 方法不会被重复调用。



ClassLoader的加载过程及分析一:
http://www.iteye.com/topic/703842
引用
虚拟机一启动,会先做一些初始化的动作。一旦初始化动作完成之后,就会产生第一个类别加载器,即所谓的Bootstrap Loader,Bootstrap Loader 是由C++ 所撰写而成,这个Bootstrap Loader所做的初始工作中,除了也做一些基本的初始化动作之外,最重要的就是加载定义在sun.misc 命名空间底下的Launcher.java 之中的ExtClassLoader( 因为是inner class ,所以编译之后会变成Launcher$ExtClassLoader.class) ,并设定其Parent 为null,代表其父加载器为Bootstrap Loader 。然后Bootstrap Loader ,再要求加载定义于sun.misc 命名空间底下的Launcher.java 之中的AppClassLoader( 因为是inner class,所以编译之后会变成Launcher$AppClassLoader.class) ,并设定其Parent 为之前产生的ExtClassLoader 实例。

AppClassLoader 和ExtClassLoader 都是URLClassLoader 的子类别。由于它们都是URLClassLoader 的子类别,所以它们也应该有URL 作为搜寻类别档的参考,由原始码中我们可以得知,AppClassLoader 所参考的URL 是从系统参java.class.path 取出的字符串所决定,而java.class.path 则是由我们在执行java.exe 时,利用 –cp 或-classpath 或CLASSPATH 环境变量所决定。

提醒我:关于JVM启动过程记得把附件中的 Using the BootClasspath.pdf 好好看看!


classloader相关基础知识:
http://www.iteye.com/topic/25053
引用
java动态载入class的两种方式:
1)implicit隐式,即利用实例化才载入的特性来动态载入class
2)explicit显式方式,又分两种方式:
  1)java.lang.Class的forName()方法
  2)java.lang.ClassLoader的loadClass()方法



深入了解Java ClassLoader、Bytecode 、ASM、cglib:
http://www.iteye.com/topic/98178


Java类加载原理解析第一篇(上):
http://weiwu83.iteye.com/blog/141207
Java类加载原理解析第一篇(下):
http://weiwu83.iteye.com/blog/141208



JDK引述:
引用

Every Class object(每个Class类的实例对象) contains a reference to the ClassLoader that defined it.


protected Class<?> loadClass(String name,boolean resolve) throws ClassNotFoundException

    Loads the class with the specified binary name. The default implementation of this method searches for classes in the following order:

       1.Invoke findLoadedClass(String) to check if the class has already been loaded.
       2. Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
       3.Invoke the findClass(String) method to find the class.

    If the class was found using the above steps, and the resolve flag is true, this method will then invoke the resolveClass(Class) method on the resulting Class object.

    Subclasses of ClassLoader are encouraged to override findClass(String), rather than this method.
分享到:
评论

相关推荐

    Dynamic Class Loading in the JavaTM Virtual Machine

    Class loaders are a powerful mechanism for dynamically loading software components on the Java platform. They are unusual in supporting all of the following features: laziness, type-safe linkage, user...

    java mongo jar包 && 完整权限配置

    mongo-java-driver-3.4.1.jar spring-data-commons-1.10.0.RELEASE.jar spring-data-commons-core-1.4.1.RELEASE.jar spring-data-mongodb-1.7.0.RELEASE.jar mongodb.xml mongodb.properties 补充说明:mongo服务器...

    浅谈java中的四个核心概念

    在Java中,类加载是一项非常重要的任务,因为它负责将Java源代码编译后的字节码文件(.class文件)加载到内存中,并准备运行时环境。类加载机制的主要功能包括: 1. **加载**:将字节码文件读入内存,并转化为二...

    深入理解Java虚拟机笔记(带目录).docx

    Java 虚拟机(JVM)是 Java 语言的运行环境,它负责解释和执行 Java 字节码。下面是 Java 虚拟机相关的知识点: 虚拟机内存结构 Java 虚拟机的内存结构主要包括以下几个部分: * 方法区(Method Area):用于存储...

    Axis2完美教程java c#调用.doc

    【标题】:“Axis2完美教程java c#调用.doc” 【描述】中提到的“Axis2完美教程”是一份详尽的指南,旨在帮助读者掌握Apache Axis2框架的使用,特别是如何通过Java和C#客户端进行调用。该文档可能涵盖了Axis2的基本...

    java_standards_v1.0neaf_2.rar_java programming

    An effective mechanism of institutionalizing production of quality code is to develop programming standard and enforce the same through code reviews. This document delves into some fundamental Java ...

    Apache错误suEXEC mechanism enabled解决

    日志错误error_log.log 提示: suEXEC mechanism enabled 日志nss_error_log.log 提示: [Sun Nov 27 16:46:38 2016] [error]Certificate not verified: 'Server-Cert' [Sun Nov 27 16:46:38 2016] [error] SSL ...

    The Java Virtual Machine Specification 3rd

    - 通过引入新的类文件格式和字节码指令,增强了JVM对于动态类型语言的支持能力。 3. **模块系统(Module System)** - Java 9引入了模块系统(Modules System),使得Java应用程序和库能够按照模块化的方式进行组织和...

    java7帮助文档

    Java Platform Standard Edition 7 Documentation What's New Documentation Release Notes Tutorials and Training The Java Tutorials Java Training More Information Java SE 7 Names and ...

    Java动态调用webService,axis2动态调用webService

    在Java开发中,Web服务(Web Service)是一种用于应用程序之间通信的技术,允许不同系统之间的数据交换。Axis2是Apache软件基金会开发的一个Web服务框架,它提供了动态调用Web服务的能力。本文将深入探讨如何使用...

    Java SE 6: Top 10 Features

    Java SE 6通过增强的安全框架和API进一步加强了这一方面的功能。 #### 10. 质量、兼容性和稳定性 最后,Java SE 6致力于提供高质量、高兼容性和高度稳定的开发环境。这一目标体现在对现有特性的优化和新功能的加入...

    Java动态类加载机制应用研究.pdf

    自定义类加载器可以扩展或替代默认的类加载器,实现一些特殊的加载策略,比如动态加载加密后的字节码文件,从而增强代码的安全性。 Java动态加载机制的原理是指类加载器按照需要加载类,这通常发生在类被首次引用时...

    map of java平台

    - **`javac`**:Java编译器,用于将Java源代码编译成字节码。 - **`javadoc`**:文档生成工具,根据源代码中的注释自动生成HTML格式的文档。 - **`apt`**:注解处理工具,允许在编译时通过注解处理器生成源代码。 - ...

    Functional Mechanism:差异隐私下的回归分析-开源

    功能机制是为大量基于优化的分析而设计的差分私有方法。 主要思想是通过扰动优化问题的目标函数而不是其结果来实施ε差分隐私。 如果您选择使用此代码,请引用以下文章:J. Zhang,Z。Zhang,X。...

    Whitworth Quick Return Mechanism:使用 Simscape Multibody 模拟 Whitworth Quick Return Mechanism-matlab开发

    使用 Simscape Multibody 模拟 Whitworth 快速返回机制。 指定旋转接头的转速。

    JAVA手机程序入门2

    ### JAVA手机程序入门2:深入理解Java包机制与动态链接本质 #### Java包机制:构建模块化编程的基础 Java的包机制(Package Mechanism)是Java语言为了支持大型项目管理和组织代码而设计的一个重要特性。它允许...

Global site tag (gtag.js) - Google Analytics