本文转载自http://tech.it168.com/a2009/0901/672/000000672382.shtml
【IT168 专稿】 本文将会从Java平台本身的类加载机制谈起,然后向读者展现WebSphere Application Server(WAS)中如何应用扩展Java本身的类加载机制。本文还将给出一些常见的由类加载的造成的问题,分析背后的原因,并给出相应的解决方案。
关键字:
JVM — Java Virtual Machine,Java虚拟机,是运行Java程序的平台,不同的操作系统有不同的实现。
classloader — 类加载器,是JVM的一个重要组件,完成加载Java Class文件进JVM。
Class — Java类型定义文件,定义的数据与相应操作方法,可被classloader加载到JVM上根据它产生相应的运行实例,并可以调用相应的方法。
让我们从最基本的说起 — Java平台的类加载机制
首先大家要知道为什么要有classloader,它是做什么的?
Java是一门语言,但它更一个平台,因为它提供了一个运行平台JVM(虚拟机),隔离了将要运行的程序与当前所在的操作系统。
而在Java这个平台要运行什么本身是动态未知的,我们写的Java程序都是在需要的时候被动态的加载上去的。Java本身提供了一套类加载机器。总的来说,所有装在Java虚拟机上运行的类都是由classloader这个东西来完成的。
那classloader是如何工作的?
首先要强调一点,所有的Java类都是由classloader动态的加载到Java虚拟机上然后再动行的。这里的动态主要表现方式是三种,见表1。
表1 Java的动态加载特性
当JVM(Java虚拟机)默认启动时,会形成由三个类加载器组成的初始类加载器层次结构:
bootstrap classloader
|
extension classloader
|
system classloader
bootstrap classloader — 引导(也称为原始)类加载器,它负责加载Java的核心类。
extension classloader — 扩展类加载器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的)中JAR的类包。
system classloader — 系统(也称为应用)类加载器,它负责在JVM被启动时,加载来自在命令java中的-classpath或者java.class.path系统属性或者CLASSPATH操作系统属性所指定的JAR类包和类路径。
如上所示,classloader是有父子结构的,如system classloader的父亲是extension classloader,extension classloader的父亲bootstrap classloader,bootstrap classloader没有父亲,它是JVM一启动就存在的。
我们还可以扩展已有的Classloader类,通过覆盖ClassLoader的findClass方法来实现自己的载入策略,甚至覆盖loadClass方法来实现自己的载入过程,这样来满足加载特定类的需求(比如只加载名字前缀是ABC的类)。这样它就成了system classloader下面的第四层。当然,因为这个我们扩展的classloader本身也是一个Java类,它也是被前面的某个classloader加载进来的.
在默认的JVM设计中,classloader加载Class的过程大致如下:
1.检测此Class是否载入过(即在JVM中是否有此Class),如果有到第8,如果没有到第2。
2.如果父亲classloader不存在(没有父亲,那一定是bootstrap classloader了),到第4。
3.请求父亲classloader载入,如果成功到第8,不成功到第5。
4.请求JVM让bootstrap classloader去加载,如果成功到第8。
5.寻找Class文件(从与此classloader相关的类路径中寻找)。如果找不到则到第7。
6.从文件中载入Class,到第8。
7.抛出ClassNotFoundException。
8.返回Class。
我们可以看到,classloader加载Class的顺序是先委托其parent来加载,直到所有的parent都不能加载才自己去加载。
Java使用classloader原因,除了可以达到动态性之外,其实最重要的原因还有安全性,体现在下面两点:
1.核心的类不可能被仿照(这主要是因为先parent委托机制的作用),比如我们不可能加载一个自己写的放在classpath下的java.lang.String类,因为Java总是parent优先,在系统目录下面的String类总是被优先加载。
2.我们可以指定,控制到特定的载入点,不会误用,比如我只要加载目录的ABC下面的类。
Java中每个类别都是与加载其进虚拟机的classloader相关联起来的,在同一个运行时的虚拟机中,同一个类型可以被不同的classloader载入多次。
WAS中的类加载机制
了解完Java本身提供的类加载机制后,下面我们看一下WebSphere Application Server(WAS)是如何利用并扩展JVM默认的已有的类加载框架。
如下是WAS的classloader层次,这里的每一层次可能有多个有父子关系的classloader组成,只是它们的目的是相同或者相关的,所以放在同一层,如表2所示。
表2 WAS Classloader层次
下面介绍每个层次的classloader所能完成的事,以从顶至下的顺序。注意,区别于JVM默认classloader加载类策略的父亲优先(PARENT_FIRST)的加载策略,WAS中有些扩展的classloader层次可以定义自己的委托策略,比如是父亲优先(PARENT_FIRST)或者父亲最后(PARENT_LAST)。
1) JVM Classloader层
这个层其实就是前面介绍的Java基本的classloader框架,由bootstrap classloader、extension classloader、system classloader三个classloader组成,主要是完成jre/lib下,java.ext.dir下,还有JVM classpath下面类的加载。
2) WebSphere Extensions Classloader层
这个层的classloader主要完成WAS运行时所需要的类以及相关资源,比如JDBC,Resource Adapter,以及用户扩展WAS运行时库的目录,这一层的委托策略都是父亲优先(PARENT_FIRST)。
3) WebSphere lib/app Class loader
这个层的classloader主要是为了兼容WAS Version 4的。它主要用来加载一些所有应用都共享的类,在Version 4以后,推荐用Shared libraries来放需要共享的类库,所以这里就不详细介绍它了。
4) WebSphere "server" Class loader
这层的classloader主要是来加载整个运行上当前服务器上的应用程序所共享的的类库,你可以通过定义特定的Shared libraries以来使当前的服务器中的应用程序共享它,这一层的委托策略是父亲优先(PARENT_FIRST)。
5) Application Class loader
下面我们到了WASclassloader的最底层。这一层由两个classloader组成:
第一个是Application Module Class loader,主要负责加载应用程序单元。对于应用程序中的Web单元,我们还可以设定用一个Web Module Class loader去加载(这时它的父亲就是Application Module Class loader),它是WAS classloader中的最底层。
对于这两个classloader,可以采取的委托策略可以既是父亲优先(PARENT_FIRST),也可以父亲最后(PARENT_LAST)。
同时,我们还可以指点是单个Application Module Class loader去加载所有的应用程序或者每个应用程序都有自己的Application Module Class loader,这是也为更好的提高classloader的隔离性(Isolation),其选项分别为Multiple与Single。
为了给大家一个直观的感觉,下面给出一个例子说明一个实际项目中classloader的使用情况。
如下图所示,在WAS上有两个应用程序:Application 1与Applicatoin 2。这个WAS的Application Module Class loader策略被指定成Multiple,这样每个应用程序都会有一个classloader。同时Application 1的Web Module类加载策略被设成“Module”,这样它就会有一个相应的Web Module Class loader来加载相应的web单元。相反,Application 2的Web Module类加载策略被设成“Application”,这样加载Application 2的classloader还会加载它的web单元,见图1。
图1 Application 1与Applicatoin 2的classloader结构
WAS中classloader的最佳实践与常见问题分析解决
下面是一些使用WAS classloader的最佳实践:
1) 不要把应用程序依赖的资源放在JVM的系统lib下让JVM的classloader去加载,原因是如果应用程序的委托策略设成PARENT_LAST,可能会造ClassNotFoundException。
2) 不要修改ws.ext.dirs这个系统属性以此来增加WebSphere Extensions Classloader的加载能力,原因是被扩展的目录可能跟当前已经目录中有冲突,会导致一此不可预期的问题。
3) 如开启了动态重加载,这种情况下应用如果有对本地类库的依赖关系,最好使用WebSphere "server" Class loader来加载,这样服务器的整个生命周期这些库都能被应用程序可见,即使应用程序被重新加载。
下面再给出两个实际WAS classloader的相关问题的分析与相应解决方案。
1) 如果在启动程序时出现如下异常:
· ClassCastException
· ClassNotFoundException
· NoClassDefFoundException
· UnsatisfiedLinkError
主要原因是未正确配置负责装入应用程序各单元的类装入器,可以查看一下当前应用程序的类加载结构。一般,我们可以从SystemOut.log这个log文件中找出当前的类加载路径设置,其中包括要加载的库以及还有WAS的扩展目录等。我们还可以利用WAS提供的Class Loader Viewer来更直接的看当前应用程序的类加载情况,方法如下:
单击Troubleshooting->Class Loader Viewer,进去后可以看到当前服务器上所有的应用程序,然后选取你关注的,然后会列出这个应用的所有组成单元,点击出现异常的那个单元,就会出现这个单元的classloader结构图,依次可以看到从顶到底的classloader结构图,并可以看到所有可以被加载的类或者类库。这样,可以分析当前出现的异常是不是因为不在这个单元的可加载视图里面,或者是不是因为跟别的当前能被加载的类有冲突。图2是一个查看实际应用程序的例子。
图2 查看应用程序的类加载情况
2) 为何更新了应用的Resource Adapter,但不起作用?
经常会有这样的情况,假设我们的应用原来用某个版本的Resource Adapter去联连后面的业务系统,因为有了新版本的Resource Adapter,我们更新了应用中的Resource Adapter,然后重新build后发布到服务器上。但是发现这个新版本的某个功能没有起作用。这里可能的原因是当前的服务器上你曾经有过以standalone的方式(让所有应用程序共享)安装了旧版本的Resource Adapter,如图3所示如何查看当前服务器上安装的standalone Resource Adapter。
图3 查看WAS已经安装的standalone Resource Adapter
如果以Standalone方式安装了旧版本的话,即使你的应用程序中包括了最新的Resource Adapter,但它也不会起作用,原因是应用的类加载默认策略是父亲优先(PARENT_FIRST),它会让WebSphere Extensions Classloader先去试着加载Resource Adapter,而WebSphere Extensions Classloader会把standalone安装的Resource Adapter加载进内存来给应用程序使用。解决方法是更新这个standalone Resource Adapter或者卸载它。
读者可以学习参考资料部分的资料来进一步提高对WAS classloader的了解。
参考资料:
Inside The Java Virtual Machine by Bill Vennershttp://www.amazon.com/Inside-Java-Virtual-Machine-Venners/dp/0071350934
IBM RedBook : WebSphere Application Server V6.1 : System Management and Configurationhttp://www.redbooks.ibm.com/abstracts/sg247304.html?Open
TroubleShooting: Classloader problems for WebSphere Application Server http://www-01.ibm.com/support/docview.wss?rs=180&uid=swg21219358
分享到:
相关推荐
这种情况往往源于日志框架配置不完整或WebSphere特有的类加载机制冲突,下面将详细介绍解决方案。 ### 解决方案详解 #### 1. 修改commons-logging.jar 首先,需要对commons-logging.jar进行修改,这是为了让...
WebSphere是IBM公司的一款强大的企业级应用服务器,它在IT行业内扮演着至关重要的角色,尤其在企业级Java应用程序的部署和管理方面。山大2014年WebSphere考试题旨在检验学生对WebSphere平台的理解和操作能力。下面将...
2. **获取配置文件路径问题**:WebSphere与Tomcat环境下的资源加载机制不同。如果在`getClassLoader().getResource("").getPath()`中获取配置文件失败,可尝试将配置文件移动到`${WAS_INSTALL_ROOT}/profiles/AppSrv...
6. **设置权限与认证**:WebSphere MQ支持多种安全机制,包括基本的用户ID和密码、LTPA(Lightweight Third-Party Authentication)、Kerberos等。你需要配置安全性,确保只有授权的用户和应用程序能够访问队列和...
WebSphere是IBM公司推出的一款企业级应用服务器,它是Java EE(Java Platform, Enterprise Edition)平台的实现,主要用于构建和部署分布式应用程序。WebSphere在企业级环境中广泛应用于电子商务、供应链管理、客户...
Websphere Application Server 6 是IBM公司推出的一款企业级应用服务器,它为开发、部署和管理Java EE(现在称为Jakarta EE)应用程序提供了强大的平台。在深入探讨其配置与管理之前,我们首先需要了解Java EE的概念...
- 上传部署:在WebSphere管理控制台中选择部署选项,上传并配置你的应用,指定上下文根、类加载器策略等。 - 启动应用:部署完成后,启动服务器实例,你的应用将自动启动。 5. **安全管理** - 用户认证:配置...
- 配置应用服务器的类加载器,确保RichFaces的库能被正确加载。可能需要调整类加载策略,避免类冲突。 4. **部署Demo**: - 提交配置并启动部署过程。WebSphere会解析`.war` 文件,并将其部署到服务器上。 - ...
文档还探讨了在WAS中实现自定义多线程编程和类加载器的可能性,以及在WebSphere应用服务器集群环境中应用程序间的相互访问问题。最后,它讨论了EJB部署代码的生成时机以及Java EE开发的最佳实践。 集群部分,文档为...
- **缓存策略**:提供缓存机制,减少服务器负载,提高页面加载速度。 8. **监控与管理** - **日志和跟踪**:详细的日志记录和跟踪功能,用于故障排查和性能分析。 - **管理工具**:提供图形化管理控制台,方便...
应用服务器(如IBM WebSphere Application Server)的性能直接影响门户的响应时间和可扩展性。文档提供了详细的JVM调优指南,包括初始和最大堆大小、大页内存设置等,以确保JVM能够有效管理内存资源。 #### JVM堆...
WebSphere Application Server 6.0无人执守部署是IBM企业级应用服务器在自动化运维场景下的一项重要技术。这项技术使得管理员能够预配置和自动化安装、配置以及管理WebSphere实例,大大提高了IT运营效率,减少了手动...
WebSphere Portal 7 支持多种服务器拓扑结构,包括单机部署和集群部署等。用户可以根据自己的业务需求选择最适合的部署方式。 ##### Web 内容管理拓扑 对于需要使用 Web 内容管理功能的场景,还需要特别考虑其拓扑...
- **为什么这种方式有效**:由于WebSphere的类加载器策略,当应用程序尝试加载某个类时,它会首先在其自己的类加载器中查找,然后才会向上级类加载器(例如,共享库类加载器)请求类。因此,如果特定版本的JCL JAR...
### WSRP与Remote Portlet在IBM WebSphere Portal Server v6.0中的应用 #### 一、WSRP简介 WSRP(Web Services for Remote Portlets)是一种标准协议,旨在允许远程portlet通过web服务接口集成到门户环境中。它...
博客中提到的源码分析,意味着我们可以深入到Java运行时系统的内部,查看ClassLoader的具体实现,例如`sun.misc.Launcher$AppClassLoader`是Java应用的默认类加载器,而`BootStrapClassLoader`是根加载器,负责加载...
### CXF支持WAS与Weblogic应用服务器 #### 概述 ...针对不同的应用服务器环境,CXF提供了详细的配置指导和最佳实践。遵循这些指南可以帮助开发者顺利部署和运行CXF应用,同时避免常见的类加载冲突等问题。