- 浏览: 103096 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
qiushuzhao:
';lll
spring data redis源码框架分析 -
qiushuzhao:
[color=yellow][/color]lll
spring data redis源码框架分析 -
jiuyuehe:
博主你好,用了你方法以后果然没有阻塞了,但是原理还是不太明白, ...
[转载]Java Process.exitValue & Process.waitFor()
JVM规范定义了两种类型的类装载器:启动内装载器
(bootstrap)
和用户自定义装载器
(user-defined class loader)
。
一.
ClassLoader
基本概念
1
.
ClassLoader
分类
类装载器是用来把类(class)装载进JVM的。
JVM规范定义了两种类型的类装载器:启动内装载器
(bootstrap)
和用户自定义装载器
(user-defined class loader)
。
JVM在运行时会产生三个ClassLoader:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader.
Bootstrap是用C++编写的,我们在Java中看不到它,是null,是JVM自带的类装载器,用来装载核心类库,如java.lang.*等。
AppClassLoader
的
Parent
是
ExtClassLoader
,而
ExtClassLoader
的
Parent
为
Bootstrap ClassLoader
。
Java
提供了抽象类
ClassLoader
,所有用户自定义类装载器都实例化自
ClassLoader
的子类。
System Class Loader
是一个特殊的用户自定义类装载器,由
JVM
的实现者提供,在编程者不特别指定装载器的情况下默认装载用户类
。系统类装载器可以通过ClassLoader.getSystemClassLoader() 方法得到。
例1,测试你所使用的JVM的ClassLoader
/*LoaderSample1.java*/
public static void main(String[] args) {
Class c;
ClassLoader cl;
cl = ClassLoader.getSystemClassLoader();
System.out.println(cl);
while (cl != null ) {
cl = cl.getParent();
System.out.println(cl);
}
try {
c = Class.forName( " java.lang.Object " );
cl = c.getClassLoader();
System.out.println( " java.lang.Object's loader is " + cl);
c = Class.forName( " LoaderSample1 " );
cl = c.getClassLoader();
System.out.println( " LoaderSample1's loader is " + cl);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在我的机器上(Sun Java 1.4.2)的运行结果
sun.misc.Launcher$AppClassLoader@1a0c10f
sun.misc.Launcher$ExtClassLoader@e2eec8
null
java.lang.Object's loader is null
LoaderSample1's loader is sun.misc.Launcher$AppClassLoader@1a0c10f
第一行表示,系统类装载器实例化自类sun.misc.Launcher$AppClassLoader
第二行表示,系统类装载器的parent实例化自类sun.misc.Launcher$ExtClassLoader
第三行表示,系统类装载器parent的parent为bootstrap
第四行表示,核心类java.lang.Object是由bootstrap装载的
第五行表示,用户类LoaderSample1是由系统类装载器装载的
二.
parent delegation模型
从1.2版本开始,Java引入了双亲委托模型,从而更好的保证Java平台的安全。在此模型下,当一个装载器被请求装载某个类时,它首先委托自己的
parent
去装载,若
parent
能装载,则返回这个类所对应的
Class
对象,若
parent
不能装载,则由
parent
的请求者去装载
。
图 1 parent delegation模型
如
图1所示,loader2的parent为loader1,loader1的parent为system class
loader。假设loader2被要求装载类MyClass,在parent
delegation模型下,loader2首先请求loader1代为装载,loader1再请求系统类装载器去装载MyClass。若系统装载器能成
功装载,则将MyClass所对应的Class对象的reference返回给loader1,loader1再将reference返回给
loader2,从而成功将类MyClass装载进虚拟机。若系统类装载器不能装载MyClass,loader1会尝试装载MyClass,若
loader1也不能成功装载,loader2会尝试装载。若所有的parent及loader2本身都不能装载,则装载失败。
若有一
个能成功装载,实际装载的类装载器被称为定义类装载器,所有能成功返回Class对象的装载器(包括定义类装载器)被称为初始类装载器。如图1所示,假设
loader1实际装载了MyClass,则loader1为MyClass的定义类装载器,loader2和loader1为MyClass的初始类装
载器。
需要指出的是,Class Loader是对象,它的父子关系和类的父子关系没有任何关系。
那么parent delegation模型为什么更安全了?因为在此模型下用户自定义的类装载器不可能装载应该由父亲装载器装载的可靠类,从而防止不可靠甚至恶意的代码代替由父亲装载器装载的可靠代码。实际上,类装载器的编写者可以自由选择不用把请求委托给
parent
,但正如上所说,会带来安全的问题。
三.命名空间及其作用
每个类装载器有自己的命名空间,命名空间由所有以此装载器为创始类装载器的类组成。不同命名空间的两个类是不可见的,但只要得到类所对应的Class对象的reference,还是可以访问另一命名空间的类。
例
2演示了一个命名空间的类如何使用另一命名空间的类。在例子中,LoaderSample2由系统类装载器装载,LoaderSample3由自定义的装
载器loader负责装载,两个类不在同一命名空间,但LoaderSample2得到了LoaderSample3所对应的Class对象的
reference,所以它可以访问LoaderSampl3中公共的成员(如age)。
例2不同命名空间的类的访问
/*LoaderSample2.java*/
import java.lang.reflect. * ;
public class LoaderSample2 {
public static void main(String[] args) {
try {
String path = System.getProperty( " user.dir " );
URL[] us = { new URL( " file:// " + path + " /sub/ " )};
ClassLoader loader = new URLClassLoader(us);
Class c = loader.loadClass( " LoaderSample3 " );
Object o = c.newInstance();
Field f = c.getField( " age " );
int age = f.getInt(o);
System.out.println( " age is " + age);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*sub/Loadersample3.java*/
static {
System.out.println( " LoaderSample3 loaded " );
}
public int age = 30 ;
}
编译:javac LoaderSample2.java; javac sub/LoaderSample3.java
运行:java LoaderSample2
LoaderSample3 loaded
age is 30
从运行结果中可以看出,在类LoaderSample2中可以创建处于另一命名空间的类LoaderSample3中的对象并可以访问其公共成员age。
运行时包(runtime package)
由
同一类装载器定义装载的属于相同包的类组成了运行时包,决定两个类是不是属于同一个运行时包,不仅要看它们的包名是否相同,还要看的定义类装载器是否相
同。只有属于同一运行时包的类才能互相访问包可见的类和成员。这样的限制避免了用户自己的代码冒充核心类库的类访问核心类库包可见成员的情况。假设用户自
己定义了一个类java.lang.Yes,并用用户自定义的类装载器装载,由于java.lang.Yes和核心类库java.lang.*由不同的装
载器装载,它们属于不同的运行时包,所以java.lang.Yes不能访问核心类库java.lang中类的包可见的成员。
总结
命名空间并没有完全禁止属于不同空间的类的互相访问,双亲委托模型加强了
Java
的安全,运行时包增加了对包可见成员的保护。
四、创建自己的类加载器
package com.alibaba.ptqa.com.alibaba.ptqa.classloader; /** * Copyright 1999-2100 Alibaba.com All right reserved. This software is the confidential and proprietary information of * Alibaba.com ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only * in accordance with the terms of the license agreement you entered into with Alibaba.com. * * @Author: leon * @Date: 11-9-28 * @Time: 下午2:47 */ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class MyClassLoader extends ClassLoader { private static final String drive = "C:/"; private static final String fileType = ".class"; public MyClassLoader() { super(); } public Class findClass(String name) { byte[] data = loadClassData(name); //The method defineClass converts an array of bytes into an instance of class Class return defineClass(name, data, 0, data.length); } public byte[] loadClassData(String name) { FileInputStream fis = null; byte[] data = null; try { fis = new FileInputStream(new File(drive + name + fileType)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int ch = 0; while ((ch = fis.read()) != -1) { baos.write(ch); } data = baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return data; } public static void main(String[] args) throws Exception { MyClassLoader loader = new MyClassLoader(); Class objClass = loader.loadClass("Helloworld", true); Object obj = objClass.newInstance(); System.out.println(objClass.getName()); System.out.println(objClass.getClassLoader()); } }
输出结果:
Helloworld
com.alibaba.ptqa.com.alibaba.ptqa.classloader.MyClassLoader@7000a32b
根据指定的名字来加载类,这一方法默认的实现按照以下的顺序调用
1. 调用 findLoadedClass(String)检查该.class文件是否已经加载
2. 调用父类的loadClass方法. 如果父的类加载器为null,则使用系统内嵌的bootStrap类加载器加载。
3. 调用findClass返回Class对象
如果按照上述方式执行,并且resovle变量为true,这个方法会对findClass方法返回结果调用resolveClass方法去链接Class对象。
从ClassLoader继承的子类最好重写findClass(String)方法
发表评论
-
spring data redis源码框架分析
2012-02-06 21:49 7884redis是由Salvatore Sanfilippo用C语言 ... -
Java Enum
2011-10-08 20:31 1028public enum Operation { ... -
Java内部类访问
2011-10-08 17:37 900当内部类为非静态时: public class In ... -
JVM Method Table
2011-10-07 16:10 1232方法表 为了提高访问效率,必须仔细的设计存储在方法区中的 ... -
JVM Symbolic refer 2 Direct Refer
2011-10-06 17:31 2Method Area: Symbolic Referen ... -
【转载】JVM中方法区
2011-09-29 14:17 1086原文链接:http://hi.baidu. ... -
JVM初探
2011-09-29 13:49 845概念: JAVA的JVM的内存可分为5个区:堆(heap ... -
【转载】java 回调函数
2011-09-18 16:01 1040java“回调函数” 所谓 ... -
[转载]Java Process.exitValue & Process.waitFor()
2011-09-17 13:14 15298Process.exitValue() 采用非阻塞的方式返回, ... -
Java读取classpath中的文件
2011-08-29 11:06 7725/** * 类AppsImport.java的实现描 ... -
【转载】jvm的内存调优
2011-08-23 17:30 1365原文链接:http://k ... -
【转载】Java 垃圾回收策略调优,实践篇
2011-08-23 17:13 889转载自:http://www.douban.c ... -
[转载]线程sleep()和wait()的区别
2011-07-01 15:07 843线程sleep()和wait()的区别 ... -
checked Exception and RuntimeException
2011-05-29 15:25 9191. RuntimeException 虚拟机执行程序时,如果 ... -
【转载】编程式事务 声明式事务区别
2011-05-09 19:08 977原文链接:http://topic.csdn.net/u/20 ... -
[转载]java回调函数
2011-04-28 16:55 897转载自:http://www.blogjava.net/ ... -
【转载】jms topic与jms queue区别
2011-02-18 17:29 10913作者longdick http://longdick.i ... -
【转载】JAVA NIO 简介
2011-02-18 11:30 891原文链接:http://www.iteye.com/topic ... -
RTTI & Reflection(反射机制)
2011-01-16 15:45 2269RTTI & Reflection 一、RTTI(R ... -
Java编程思想中异常的限制
2011-01-08 20:55 10501. 构造函数必须抛出基类构造函数的抛出的异常; 这 ...
相关推荐
Java ClassLoader定制实例
java classloader classpath 张孝祥
Java ClassLoader Tutorial
理解Java ClassLoader机制
NULL 博文链接:https://sbiigu.iteye.com/blog/260456
java classloader 讲义-淘宝网
Understanding the Java ClassLoader
java classLoader 的全面讲解 从基本概念到具体的应用 里面共有三份资料。
Understanding the Java ClassLoader.pdf
Sun 官方关于 ClassLoader原理的文章,值得一看
本教程概述了 Java ClassLoader,并指导您构造在装入代码之前自动编译代码的示例 ClassLoader。您将完全了解 ClassLoader 的功能以及创建自己的 ClassLoader 需要执行的操作
破解java加密的ClassLoader.java,在classloader植入破解代码
内容简介: ClassLoader体系结构 类装载器在JVM中并不是唯一的,JVM自带了三个装载器,用户也可以根据自己的需求自定义新的装载器,这些装载器的体系结构可以看作是树状结构,如图1所示:
了解 Java ClassLoader
ClassLoader类加载器讲解,理解JAVA类加载机制
Java ClassLoader 是一个重要的、但又常常被人忽略的 Java 运行时系统组件。它是负责在运行时查找和装入类文件的类。创建自己的 ClassLoader 可以以实用且有趣的方式定制 JVM,这样可以让您彻底重新定义如何将类文件...
深入了解Java_ClassLoader,Bytecde.pdf
主要内容包括 Java类加载机制及加载流程,以及如何定义自己的类加载器,如何实现类的热替换。