转:jvm classloader

转:jvm classloader

作者:白菜 发布时间:September 7, 2010 分类:JAVA

1. 从一个简单小实验开始:

(1) Eclipse下建一简单Java project,写一个简单程序,如下:

  1. package com.javaeye.loader;  
  2.   
  3. public class URLClassLoaderTest {  
  4.     public void show() {  
  5.         System.out.println("I am running...");  
  6.     }  
  7. }  
package com.javaeye.loader;public class URLClassLoaderTest {	public void show() {		System.out.println("I am running...");	}}

(2) 到项目对应bin/com/javaeye/loader下找到URLClassLoaderTest.class文件,将此文件保存,然后删除整个project;

(3) 在磁盘任何位置建立文件夹com,在com里建立javaeye,在javaeye里建立loader,我建在C盘java目录下,建立完成后将(2)中保存的URLClassLoaderTest.class文件拷贝到其中,
(4) 在非本地Apache Server上任何位置建立文件夹com,在com里建立javaeye,在javaeye里建立loader文件夹,完成后将(2)中保存的URLClassLoaderTest.class文件拷贝到其中,我的非本地计算机IP为192.168.66.250,系统为Linux Redhat, 建立完成后我们可以访问
 (5) 给出两端端测试代码:

  1.                @Test  
  2. public void testInWeb() throws Exception{  
  3.     URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};  
  4.     URLClassLoader loader = new URLClassLoader(urls);  
  5.     Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");  
  6.     Method m = clas.getMethods()[0];  
  7.     Object o = clas.newInstance();  
  8.     m.invoke(o);  
  9. }  
  10. @Test  
  11. public void testInFileSystem() throws Exception{  
  12.     URL[] urls = new URL[]{new URL("file:/C:/java/")};  
  13.     URLClassLoader loader = new URLClassLoader(urls);  
  14.     Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");  
  15.     Method m = clas.getMethods()[0];  
  16.     Object o = clas.newInstance();  
  17.     m.invoke(o);  
  18. }  
                @Test	public void testInWeb() throws Exception{		URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};		URLClassLoader loader = new URLClassLoader(urls);		Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");		Method m = clas.getMethods()[0];		Object o = clas.newInstance();		m.invoke(o);	}	@Test	public void testInFileSystem() throws Exception{		URL[] urls = new URL[]{new URL("file:/C:/java/")};		URLClassLoader loader = new URLClassLoader(urls);		Class clas = loader.loadClass("com.javaeye.loader.URLClassLoaderTest");		Method m = clas.getMethods()[0];		Object o = clas.newInstance();		m.invoke(o);	}

 分别运行两端代码他们输出结果都是:

Java代码
  1. I am running...  
I am running...

 分析:

      为什么会出现上述运行结果,很明显是因为com.learn.loader.URLClassLoaderTest对象被加载到内存,此对象中的show方法被执行;

思考:

      Java 语言由于在 Java 虚拟机 (JVM) 上运行而显得与众不同,之所以与众不同是因为Java中已编译的程序是一种特殊的、独立于平台的格式,并非依赖于它们所运行的机器。在很大程度上,这种格式不同于传统的可执行程序格式。与 C 或 C++ 编写的程序不同,Java 程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件对应于一个 Java 类。此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。ClassLoader 是 JVM 中将类装入内存的工具。

 

2.jvm classLoader architecture

同样给出一个例子代码:

  1. public void testClassLoader2() throws Exception{  
  2.         URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};  
  3.         URLClassLoader loader = new URLClassLoader(urls);  
  4.         System.out.println(loader.getClass());  
  5.         System.out.println(loader.getParent().getClass());  
  6.         System.out.println(loader.getParent().getParent().getClass());  
  7.         System.out.println(loader.getParent().getParent().getParent());  
  8.     }  
public void testClassLoader2() throws Exception{		URL[] urls = new URL[]{new URL("http://192.168.66.250/root/java/")};		URLClassLoader loader = new URLClassLoader(urls);		System.out.println(loader.getClass());		System.out.println(loader.getParent().getClass());		System.out.println(loader.getParent().getParent().getClass());		System.out.println(loader.getParent().getParent().getParent());	}

 

运行结果如下:

Java代码
  1. class java.net.URLClassLoader  
  2. class sun.misc.Launcher$AppClassLoader  
  3. class sun.misc.Launcher$ExtClassLoader  
  4. null  
class java.net.URLClassLoaderclass sun.misc.Launcher$AppClassLoaderclass sun.misc.Launcher$ExtClassLoadernull

 

要解释这个运行结果需要说明jvm classloader 结构,如下图:



 如图所示,为了实现java安全沙箱模型顶层的类加载器安全机制, java默认采用了 " 双亲委派的加载链 " 结构,图中分为四层。和我们上面运行结果是一一对应的

      最底层:User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类) ,在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。显然java.net.URLClassLoader属于此层;

      AppClassLoader层:System ClassLoader/系统类加载器,主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。java.lang.ClassLoader.getSystemClassLoader()可以得到他,上述sun.misc.Launcher$AppClassLoader属于此层;

      ExtClassloader层:Extension ClassLoader/扩展类加载器,主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作,sun.misc.Launcher$ExtClassLoader属于此层;

      最顶层:Bootstrap ClassLoader/启动类加载器,主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作,为什么对应这层输出为null?是因为Bootstrap是用C++编写的,我们在Java中看不到它,是null;
来自于:http://www.javaeye.com/topic/753834

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值