理解WAS 6.1的类加载(1)

 
   | |

导读:类加载器负责把类加载到Java虚拟机JVM中。指定类的名称,类加载器就会定位这个类的定义,Java类必须由类加载器加载。处理类加载器时,父委托模式是一个需要理解概念。

关键词:类加载器 Java虚拟机 JVM 父委托模式 WAS

 
正在加载数据...

  12.1 Java类加载器介绍

  类加载器负责把类加载到Java虚拟机(JVM)中。指定类的名称,类加载器就会定位这个类的定义,每一个Java类必须由类加载器加载。

  当启动JVM的时候,可以使用三个类加载器:引导(bootstrap)类加载器、扩展(extensions)类加载器、应用程序(application)类加载器。

  1.引导类加载器仅仅负责加载核心的Java库,比如位于<JAVA_HOME>/jre/lib 目录下的vm.jar,core.jar。这个类加载器,是JVM核心部分,是用native代码写成的。

  2. 扩展类加载器负责加载扩展路径下的代码,一般位于<JAVA_HOME>/jre/lib/ext  或者通过java.ext.dirs 这个系统属性指定的路径下的代码。这个类加载器是由sun.misc.Launcher$ExtClassLoader 实现的。

  3.应用程序类加载器负责加载java.class.path(映射系统参数 CLASSPATH的值) 路径下面的代码,这个类加载器是由 sun.misc.Launcher$AppClassLoader 实现的。

  当处理类加载器时,父委托模式是一个需要理解的关键概念。它规定:类加载器在加载自己的类之前,可以委托先加载父类。父类加载器可以是客户化的类加载器或者引导类加载器。但是有一点很重要,类加载器只能委托自己的父类加载器,而不能是子类加载器(只能向上不能向下)。

  扩展类加载器是应用程序类加载器的父亲。类加载器的层次图见图12-1 。

  图12-1 类加载器层次图

  如果应用程序类加载器需要加载一个类,它首先委托扩展类加载器,扩展类加载器再委托引导类加载器。如果父类加载器不能加载类,子类加载器就回在自己的库中查找这个类。基于这个特性,类加载器只负责它的祖先无法加载的类。

  如 果类加载器加载一个类,这个类不是在类加载器树上的叶子节点上,就会出现一些有趣的问题。比如例12-1,一个名为WhichClassLoader1 的类加载了一个名为WhichClassLoader2类,WhichClassLoader2又调用了名为WhichClassLoader3的类。

  例12-1 WhichClassLoader1 和 WhichClassLoader2 源代码

  public class WhichClassLoader1 {

  public static void main(String[] args) throws javax.naming.NamingException

  {

  // Get classpath values

  String bootClassPath = System.getProperty("sun.boot.class.path");

  String extClassPath = System.getProperty("java.ext.dirs");

  String appClassPath = System.getProperty("java.class.path");

  // Print them out

  System.out.println("Bootstrap classpath =" + bootClassPath + "\n");

  System.out.println("Extensions classpath =" + extClassPath + "\n");

  System.out.println("Application classpath=" + appClassPath + "\n");

  // Load classes

  Object bj = new Object();

  WhichClassLoader1 wcl1 = new WhichClassLoader1();

  WhichClassLoader2 wcl2 = new WhichClassLoader2();

  // Who loaded what?

  System.out.println("Object was loaded by "

  + obj.getClass().getClassLoader());

  System.out.println("WCL1 was loaded by "

  + wcl1.getClass().getClassLoader());

  System.out.println("WCL2 was loaded by "

  + wcl2.getClass().getClassLoader());

  wcl2.getTheClass();

  }

  }

  ======================================================================
 
  public class WhichClassLoader2 {

  // This method is invoked from WhichClassLoader1

  public void getTheClass() {

  WhichClassLoader3 wcl3 = new WhichClassLoader3();

  System.out.println("WCL3 was loaded by "

  + wcl3.getClass().getClassLoader());

  }

  }

  如 果所有的WhichClassLoaderX 类都放在应用程序的类路径下,三个类就会被应用程序类加载器加载,这个例子就会运行正常。现在假定把WhichClassLoader2 类文件打包成JAR文件放在<JAVA_HOME>/jre/lib/ext 目录下,运行WhichClassLoader1,就会看到例12-2的输出:

  例12-2 NoClassDefFoundError  异常跟踪

  Bootstrap classpath

  =C:\WebSphere\AppServer\java\jre\lib\vm.jar;C:\WebSphere\AppServer\java\jre\lib

\core.jar;C:\WebSphere\AppServer\java\jre\lib\charsets.jar;C:\WebSphere\AppServ

er\java\jre\lib\graphics.jar;C:\WebSphere\AppServer\java\jre\lib\security.jar;C

:\WebSphere\AppServer\java\jre\lib\ibmpkcs.jar;C:\WebSphere\AppServer\java\jre\

lib\ibmorb.jar;C:\WebSphere\AppServer\java\jre\lib\ibmcfw.jar;C:\WebSphere\AppS

erver\java\jre\lib\ibmorbapi.jar;C:\WebSphere\AppServer\java\jre\lib\ibmjcefw.j

ar;C:\WebSphere\AppServer\java\jre\lib\ibmjgssprovider.jar;C:\WebSphere\AppServ

er\java\jre\lib\ibmjsseprovider2.jar;C:\WebSphere\AppServer\java\jre\lib\ibmjaa

slm.jar;C:\WebSphere\AppServer\java\jre\lib\ibmjaasactivelm.jar;C:\WebSphere\Ap

pServer\java\jre\lib\ibmcertpathprovider.jar;C:\WebSphere\AppServer\java\jre\li

b\server.jar;C:\WebSphere\AppServer\java\jre\lib\xml.jar

Extensions classpath =C:\WebSphere\AppServer\java\jre\lib\ext

Application classpath=.

Exception in thread "main" java.lang.NoClassDefFoundError: WhichClassLoader3

at java.lang.J9VMInternals.verifyImpl(Native Method)

at java.lang.J9VMInternals.verify(J9VMInternals.java:59)

at java.lang.J9VMInternals.initialize(J9VMInternals.java:120)

at WhichClassLoader1.main(WhichClassLoader1.java:17)

  正如所看到的,由于WhichClassLoader3 在应用程序类路径下,程序失败,收到一个NoClassDefFoundError 的异常,这看起来有些奇怪。问题在于:它现在在一个错误的类路径下面。当WhichClassLoader2被扩展类加载器加载的时候,发生了什么呢?实 际上,应用程序类加载器委托扩展类加载器加载WhichClassLoader2,扩展类加载器又委托引导类加载器。由于引导类加载器找不到这个类,类加 载的控制就会返回给扩展类加载器。扩展类加载器在自己的路径下找到了这个类将它加载。现在,当一个类已经被类加载器加载后,这个类需要的任何其他的新类都 必须用同一个类加载器加载他们(或者遵循父委托模式,由父类加载器加载)。所以当WhichClassLoader2 需要访问WhichClassLoader3 的时候,扩展类加载器就会获得这个请求去加载WhichClassLoader3,扩展类加载器先委托引导类加载器,但是引导类加载器找不到这个类,于是 扩展类加载器便试图装入自身但是也找不到这个类,原因是WhichClassLoader3不在扩展类路径而是在应用程序类路径。由于扩展类加载器无法委 托应用程序类加载器,所以就会出现NoClassDefFoundError 的异常。

  注意:开发者通常会使用如下语法通过类加载器机制加载属性文件:

  Properties p = new Properties();

  p.load(MyClass.class.getClassLoader().getResourceAsStream("myApp.properties"

  ));

  这个意思是:如果MyClass 由扩展类加载器加载,而 myApp.properties 文件只能应用程序类加载器看到,则装入属性文件就会失败。


理解WAS 6.1的类加载
 理解WAS 6.1的类加载(4)
 理解WAS 6.1的类加载(3)
 理解WAS 6.1的类加载(2)
 理解WAS 6.1的类加载(1)

原文出处:http://gocom.primeton.com/blog15908_23254.htm
 
来源:goCom构客网    作者:zhanghs    
 
 
 
 
 

热门技术手册排行

 

随着开源技术越来越成熟,一个稍有开发经验的人通过学习就可以用开源的产品和技术构建一套可用的系统。对于从事软件开发的人员,尤其是对Java或动态语言相关领域的人来说,“开源”也许是他们最喜爱的单词。但是,很多时候我们需要的不仅仅是一个可用的系统,而是希望这个系统开发更简易、性能更高和扩展性更好等。这确实是一个令人头痛的问题。本指南很多地方都是点到为止,要深入了解相关信息的读者请借助参考资料、网站等自行挖掘。

 

本专题分六部分探讨SOA设计模式,当初设计面向服务架构的一大初衷就是降低服务间耦合度,由此提高服务的灵活性和自由度。

 

业务流程管理(business process management,bpm)不是一个新概念,甚至不是一个新名词。它是从相关的业务流程变革领域,如业务流程改进(bpi)、业务流程重组(bpr)、业务流程革新中发展起来的。流程管理技术也是从早期的工作流管理、eai、流程自动化、流程集成、流程建模、流程优化等技术中发展起来的。

 

TOAGF是一个架构框架,简而言之,TOGAF是一种协助发展,验收,运行,使用,和维护架构的工具。它是基于一个迭代(Iterative)的过程模型,支持最佳实践和一套可重用的现有架构资产。

 

云计算的概念越来越流行,Amazon、Google和IBM是第一批将云计算引入公众视线的公司。云计算就是新的Web2.0,一种既有技术上的市场绽放。

 

Mashup是一个非常cool的新的应用程序种类。如果你想真正的了解它们,我们需要回过头来看看你现在的计算机,其实它就是一个非常好的帮助你理解mashup的模型。现在开源的操作系统无疑是非常好的apis的集合或应用程序编程接口,帮助开发者去构建其应用程序。计算机本身也是一个很好的为用户提供接口的例子,键盘和鼠标可以被理解为你通过计算机的接口而使用的不同的应用程序。本技术手册为读者提供了一些相关信息,如果需要深入了解mashup,读者可以借助其他参考资源。

查看更多
 
 

登录TechTarget中国

关闭
本服务仅向TechTarget中国的会员开放,请登录或立即免费注册
电子邮件地址:
请输入您的电子邮件地址
密码:
下次自动登录