深入研究Java类载入机制
 
类载入是Java程序运行的第一步,研究类的载入有助于了解JVM运行过程,并指导开发人员採取更有效的措施配合程序运行。
研究类载入机制的第二个目的是让程序能动态的控制类载入,比方热部署等,提高程序的灵活性和适应性。
 
一、简单过程
 
Java程序执行的场所是内存,当在命令行下执行:
java HelloWorld
命令的时候,JVM会将HelloWorld.class载入到内存中,并形成一个Class的对象HelloWorld.class。
当中的过程就是类载入过程:
1、寻找jre文件夹,寻找jvm.dll,并初始化JVM;
2、产生一个Bootstrap Loader(启动类载入器);
3、Bootstrap Loader自己主动载入Extended Loader(标准扩展类载入器),并将其父Loader设为Bootstrap Loader。
4、Bootstrap Loader自己主动载入AppClass Loader(系统类载入器),并将其父Loader设为Extended Loader。
5、最后由AppClass Loader载入HelloWorld类。
 
以上就是类载入的最一般的过程。
 
二、类载入器各自搜索的文件夹
 
为了弄清楚这个问题,首先还要看看System类的API doc文档。
 
 
相关值的描写叙述
java.version Java 执行时环境版本号
java.vendor Java 执行时环境供应商
java.vendor.url Java 供应商的 URL
java.home Java 安装文件夹
java.vm.specification.version Java 虚拟机规范版本号
java.vm.specification.vendor Java 虚拟机规范供应商
java.vm.specification.name Java 虚拟机规范名称
java.vm.version Java 虚拟机实现版本号
java.vm.vendor Java 虚拟机实现供应商
java.vm.name Java 虚拟机实现名称
java.specification.version Java 执行时环境规范版本号
java.specification.vendor Java 执行时环境规范供应商
java.specification.name Java 执行时环境规范名称
java.class.version Java 类格式版本
java.class.path Java 类路径
java.library.path 载入库时搜索的路径列表
java.io.tmpdir 默认的暂时文件路径
java.compiler 要使用的 JIT 编译器的名称
java.ext.dirs 一个或多个扩展文件夹的路径
os.name 操作系统的名称
os.arch 操作系统的架构
os.version 操作系统的版本号
file.separator 文件分隔符(在 UNIX 系统中是“/”)
path.separator 路径分隔符(在 UNIX 系统中是“:”)
line.separator 行分隔符(在 UNIX 系统中是“/n”)
user.name 用户的账户名称
user.home 用户的主文件夹
user.dir 用户的当前工作文件夹
 
可惜这个帮助文档并不全,直接用程序打印出来例如以下:
                for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) { 

                        System.out.println(entry.getKey()+"\t"+entry.getValue()); 

                }
 
java.runtime.name Java(TM) SE Runtime Environment
sun.boot.library.path Q:\jdk6\jre\bin
java.vm.version 14.0-b16
java.vm.vendor Sun Microsystems Inc.
java.vendor.url http://java.sun.com/
path.separator ;
idea.launcher.port 7532
java.vm.name Java HotSpot(TM) Client VM
file.encoding.pkg sun.io
sun.java.launcher SUN_STANDARD
user.country CN
sun.os.patch.level Service Pack 3
java.vm.specification.name Java Virtual Machine Specification
user.dir E:\projects\testScanner
java.runtime.version 1.6.0_14-b08
java.awt.graphicsenv sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs Q:\jdk6\jre\lib\endorsed
os.arch x86
java.io.tmpdir C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\
line.separator
java.vm.specification.vendor Sun Microsystems Inc.
user.variant
os.name Windows XP
sun.jnu.encoding GBK
java.library.path Q:\jdk6\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;Q:\jdk6\bin;Q:\JavaFX\javafx-sdk1.2\bin;Q:\JavaFX\javafx-sdk1.2\emulator\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\MySQL Server 5.1\bin;C:\Program
Files\StormII\Codec;C:\Program Files\StormII
java.specification.name Java Platform API Specification
java.class.version 50
sun.management.compiler HotSpot Client Compiler
os.version 5.1
user.home d:\我的文档
user.timezone
java.awt.printerjob sun.awt.windows.WPrinterJob
idea.launcher.bin.path C:\IDEA8\bin
file.encoding UTF-8
java.specification.version 1.6
java.class.path Q:\jdk6\jre\lib\alt-rt.jar;Q:\jdk6\jre\lib\charsets.jar;Q:\jdk6\jre\lib\deploy.jar;Q:\jdk6\jre\lib\javaws.jar;Q:\jdk6\jre\lib\jce.jar;Q:\jdk6\jre\lib\jsse.jar;Q:\jdk6\jre\lib\management-agent.jar;Q:\jdk6\jre\lib\plugin.jar;Q:\jdk6\jre\lib\resources.jar;Q:\jdk6\jre\lib\rt.jar;Q:\jdk6\jre\lib\ext\dnsns.jar;Q:\jdk6\jre\lib\ext\localedata.jar;Q:\jdk6\jre\lib\ext\sunjce_provider.jar;Q:\jdk6\jre\lib\ext\sunmscapi.jar;Q:\jdk6\jre\lib\ext\sunpkcs11.jar;E:\projects\testScanner\out\production\testScanner;C:\IDEA8\lib\idea_rt.jar
user.name Administrator
java.vm.specification.version 1
java.home Q:\jdk6\jre
sun.arch.data.model 32
user.language zh
java.specification.vendor Sun Microsystems Inc.
awt.toolkit sun.awt.windows.WToolkit
java.vm.info mixed mode, sharing
java.version 1.6.0_14
java.ext.dirs Q:\jdk6\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
sun.boot.class.path Q:\jdk6\jre\lib\resources.jar;Q:\jdk6\jre\lib\rt.jar;Q:\jdk6\jre\lib\sunrsasign.jar;Q:\jdk6\jre\lib\jsse.jar;Q:\jdk6\jre\lib\jce.jar;Q:\jdk6\jre\lib\charsets.jar;Q:\jdk6\jre\classes
java.vendor Sun Microsystems Inc.
file.separator \
java.vendor.url.bug http://java.sun.com/cgi-bin/bugreport.cgi
sun.io.unicode.encoding UnicodeLittle
sun.cpu.endian little
sun.desktop windows
sun.cpu.isalist
 
1、Bootstrap Loader(启动类载入器):载入System.getProperty("sun.boot.class.path")所指定的路径或jar。
2、Extended Loader(标准扩展类载入器ExtClassLoader):载入System.getProperty("java.ext.dirs")所指定的路径或jar。在使用Java执行程序时,也能够指定其搜索路径,比如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld
 
3、AppClass Loader(系统类载入器AppClassLoader):载入System.getProperty("java.class.path")所指定的路径或jar。在使用Java执行程序时,也能够加上-cp来覆盖原有的Classpath设置,比如: java -cp ./lavasoft/classes HelloWorld
 
ExtClassLoader和AppClassLoader在JVM启动后,会在JVM中保存一份,而且在程序执行中无法改变其搜索路径。假设想在执行时从其它搜索路径载入类,就要产生新的类载入器。
 
三、类载入器的特点
 
1、执行一个程序时,总是由AppClass Loader(系统类载入器)開始载入指定的类。
2、在载入类时,每一个类载入器会将载入任务上交给其父,假设其父找不到,再由自己去载入。

3、Bootstrap Loader(启动类载入器)是最顶级的类载入器了,其父载入器为null.
 
四、类载入器的获取
 
非常easy,看以下样例
public class HelloWorld { 

        public static void main(String[] args) { 

                HelloWorld hello = new HelloWorld(); 

                Class c = hello.getClass(); 

                ClassLoader loader = c.getClassLoader(); 

                System.out.println(loader); 

                System.out.println(loader.getParent()); 

                System.out.println(loader.getParent().getParent()); 

        } 

}
 
打印结果:
sun.misc.Launcher$AppClassLoader@19821f 

sun.misc.Launcher$ExtClassLoader@addbf1 

null 



Process finished with exit code 0
 
从上面的结果能够看出,并没有获取到ExtClassLoader的父Loader,原因是Bootstrap Loader(启动类载入器)是用C语言实现的,找不到一个确定的返回父Loader的方式,于是就返回null。
 
五、类的载入
 
类载入有三种方式:
1、命令行启动应用时候由JVM初始化载入
2、通过Class.forName()方法动态载入
3、通过ClassLoader.loadClass()方法动态载入
 
三种方式差别比較大,看个样例就明确了:
public class HelloWorld { 

        public static void main(String[] args) throws ClassNotFoundException { 

                ClassLoader loader = HelloWorld.class.getClassLoader(); 

                System.out.println(loader); 

                //使用ClassLoader.loadClass()来载入类,不会运行初始化块 

                loader.loadClass("Test2"); 

                //使用Class.forName()来载入类,默认会运行初始化块 

//                Class.forName("Test2"); 

                //使用Class.forName()来载入类,并指定ClassLoader,初始化时不运行静态块 

//                Class.forName("Test2", false, loader); 

        } 

}
 
public class Test2 { 

        static { 

                System.out.println("静态初始化块运行了!"); 

        } 

}
 
分别切换载入方式,会有不同的输出结果。
 
六、自己定义ClassLoader
 
为了说明问题,先看样例:
package test; 



import java.net.MalformedURLException; 

import java.net.URL; 

import java.net.URLClassLoader; 



/** 

* 自己定义ClassLoader 



* @author leizhimin 2009-7-29 22:05:48 

*/ 

public class MyClassLoader { 

        public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException { 

                URL url = new URL("file:/E:\\projects\\testScanner\\out\\production\\testScanner"); 

                ClassLoader myloader = new URLClassLoader(new URL[]{url}); 

                Class c = myloader.loadClass("test.Test3"); 

                System.out.println("----------"); 

                Test3 t3 = (Test3) c.newInstance(); 

        } 

}
 
public class Test3 { 

        static { 

                System.out.println("Test3的静态初始化块运行了!"); 

        } 

}
 
执行后:
---------- 

Test3的静态初始化块运行了! 



Process finished with exit code 0
 
能够看出自己定义了ClassLoader myloader = new URLClassLoader(new URL[]{url});已经成功将类Test3载入到内存了,并通过默认构造方法构造了对象Test3 t3 = (Test3) c.newInstance();
 
有关ClassLoader还有非常重要一点:
同一个ClassLoader载入的类文件,仅仅有一个Class实例。可是,假设同一个类文件被不同的ClassLoader载入,则会有两份不同的ClassLoader实例(前提是着两个类载入器不能用同样的父类载入器)。

深入研究Java类载入机制的更多相关文章

  1. 深入研究Java类装载机制

    目录 1.为什么要研究java类装在机制? 2.了解类装载机制,对于我们在项目开发中有什么作用? 3.装载实现细节. 4.总结 一.为什么药研究Java类装载机制 java类加载机制,便于我们使用自定 ...

  2. Java虚拟机的类载入机制

    Java虚拟机类载入过程是把Class类文件载入到内存.并对Class文件里的数据进行校验.转换解析和初始化,终于形成能够被虚拟机直接使用的java类型的过程. 在载入阶段,java虚拟机须要完毕下面 ...

  3. java类载入器——ClassLoader

    Java的设计初衷是主要面向嵌入式领域,对于自己定义的一些类,考虑使用依需求载入原则.即在程序使用到时才载入类,节省内存消耗,这时就可以通过类载入器来动态载入. 假设你平时仅仅是做web开发,那应该非 ...

  4. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  5. JVM系列文章(四):类载入机制

    作为一个程序猿,只知道怎么用是远远不够的. 起码,你须要知道为什么能够这么用.即我们所谓底层的东西. 那究竟什么是底层呢?我认为这不能一概而论.以我如今的知识水平而言:对于Web开发人员,TCP/IP ...

  6. Java类载入器 ClassLoader的解析

    //參考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类载入器基本概念 类载入器是 Java 语言的一个创新,也是 Ja ...

  7. Java类载入器原理分析

    一:Java虚拟机中能够安装多个类载入器,系统默认是三个基本的类载入器: Bootstrap  ExtClassLoader  AppClassLoader 类载入器也是Java类.由于其它Java类 ...

  8. DexClassLoader和PathClassLoader类载入机制

    0x00 在DexClassLoader和PathClassLoader载入Dex流程一文中,我们分析了dex文件怎样形成了DexFile结构体.本文中解说类载入机制,实际上就是生成ClassObje ...

  9. Java类载入器(一)——类载入器层次与模型

    类载入器   虚拟机设计团队把类载入阶段中的"通过一个类的全限定名来获取描写叙述此类的二进制字节流"这个动作放到Java虚拟机外部去实现.以便让应用程序自己决定怎样去获取所须要的类 ...

随机推荐

  1. 如何禁止使用teamviwer的使用

    前几天有人问我teamviwer怎么禁止,刚开始做实验的时候过滤了teramviwer.com解析出来的IP,可是还是没有用,其实将teamviwer登陆的服务器地址在路由器上过滤,teramviwe ...

  2. Bootstrap之表格

    基本实例 为随意<table>标签加入.table类能够为其赋予主要的样式-少量的内补(padding)和水平方向的分隔线. <table class="table&quo ...

  3. VS2008--无法找到“XXX.exe”的调试信息,或者调试信息不匹配

    ------解决方案----- 1. 关闭掉Visual Studio 实例. 2. 找到解决方案下的.suo文件并删除之. 3. 重新启动Visual Studio,或者直接双击.sln文件打开 4 ...

  4. MyBatis一级缓存引起的无穷递归

    MyBatis一级缓存引起的无穷递归 引言: 最近在项目中参与了一个领取优惠劵的活动,当多个用户领取同一张优惠劵的时候,使用了数据库锁控制并发,起初的设想是:如果多个人同时领一张劵,第一个到达的人领取 ...

  5. CentOS 网络设置修改

    环境: 系统硬件:vmware vsphere (CPU:2*4核,内存2G) 系统版本:Centos-6.5-x86_64 路由器网关:192.168.1.1 步骤: 1.查看网络MAC地址 [ro ...

  6. 一般报java.lang.NullPointerException的原因有以下几种

    一般报java.lang.NullPointerException的原因有以下几种: ·字符串变量未初始化: ·接口类型的对象没有用具体的类初始化,比如: List lt; 会报错 List lt = ...

  7. HDU 1114 Piggy-Bank 全然背包

    Piggy-Bank Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit S ...

  8. crm工作机会实体

    using System;     using Microsoft.Xrm.Sdk;     using Microsoft.Crm.Sdk.Messages; public class Opport ...

  9. java大全经典的书面采访

    果学网  -专注IT在线www.prismcollege.com 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面.以便更充分地注意与当前目标有关的方面.抽象并 ...

  10. poj 1959 Darts 同意反复组合

    水题.直接贴代码. //poj 1959 //sep9 #include <iostream> using namespace std; int n; int f[128]; int so ...