您的位置:首页 > 编程语言 > Java开发

理解类加载器:j2ee 环境下的 log4j

2016-01-08 22:59 218 查看
类加载器。顾名思义,表示在java虚拟机中加载calsses.在我们的class执行和被访问之前。它必须通过类加载器加载使之有效。给定一个class名字,类加载器会定位class并且将它加载到java虚拟机。但是类加载器本事就是class。这就带来一个问题。是谁来加载这些类加载器呢。

  当你运行一个java程序。(例如在命令行内输入java命令),它就会执行并且启动一个本地的native java launcher(我叫他java 启动者,估计不太准确注明一下)。这里本地的意思是指针对你的平台和运行环境而言。这个本地的java启动者包含一个类加载器,这个类加载器的名字叫做bootstrap 类加载器.(引导类加载器).这个引导类加载器.是本地的和你的环境有关。而且它不是用java写成的。这个引导类加载器的主要功能是加载java的核心类。

  
 


  
figure 1; 类加载器 委托层次

  

  java虚拟机缺省会执行其他两个类加载器.引导类加载器会加载extension(扩展)类加载器和application(应用)类加载器到内存中。这些都是用java写成的。和前面提到的一样。引导类加载器会加载java的核心类(例如:java.util包下的类)。扩展类加载器会加载扩展的java核心类(例如:javax.包下的类,或者是在运行环境中类路径ext目录下的java类。)应用类加载器会加载你应用下的各种class文件。

  所有三种类加载器都遵循委托模式。当低一级的类加载器需要定位一个类。它会将这个任务委托给父一级类加载器.当你的应用需要一个特殊的类。应用类加载器会将这个任务委托给扩展类加载器.而扩展类加载器又会将这个任务委托个引导类加载器.。如果你请求的类是一个核心类。那么引导类加载器会将这个类加载,使你可以使用这个类。但是如果找不到这个类。这个请求就会返回到扩展类加载器.最后在返回到应用类加载器.这样的做法就使每个类加载器会先让它的父一级的类加载器搜索需要的类。只有当父一级的类加载器没有找到。才会让子一级的类加载器为它自己搜索所需的类。

  在应用服务器当中,每一个独立部署的web应用和ejb都会取得属于自己的类加载器(正常情况下,这也是weblogic的处理方式)。这种类加载器来源于应用类加载器.它们主要用来加载特定的ejb和web应用。(注意一点,当我们的web应用打包成ear文件?d?dejb和webapps的混合,这时候只会有一个类加载器,不会再分成ejb和webapp两种)这种新的类加载器会加载所有webapp和ejb所需要的类包。当然首先这些类包不存在于java核心类中和扩展类中(ext)。它可以加载也可以卸载类包。但它有一种缺省类加载器所没有的特性。这个特性就是可以对应用进行热部署。

  当weblogic启动的时候。它会用java提供的应用类加载器加载相应的类。并且构造相应的运行环境。然后它会启动特定的类加载器.这种特定的类加载器来源于java的应用类加载器.java的应用类加载器会为特定的类加载器加载相应的classes.这种特定的类加载器对于其他的应用的类加载器是不可见。因此。一个特定应用所加载的classes.对于其他应用是不可见的。

  



  
figure 2: 特定的应用 类加载器

  

  那么我们如何使一个单独的类对所有的应用都起作用呢。只有使用上层的类加载器.可以把这个类方在weblogic中classpath里面。当weblogic启动的时候。缺省的java 应用类加载器会自动把类加载到内存中去。所有的子应用都是可以访问到这个类的。但是。这中方法的缺点也很明显。首先你失去了在所有特定应用中对指定类进行热部署的能力。第二、这些类发生任何变化意味着server必须从新启动。因为没有一种机制可以让java应用类加载器从新加载这些类。所以当你采用这种方法的时候你要权衡一下得失。

  对你的j2ee应用来说,log4j是一种扩展类库。那么我们应该把这个类库放到那里去呢。前面提到一种建议是。将它放到weblogic启动时的classpath中。但是前面也讲到了它的缺点。不太建议使用这种方法。但是在j2ee环境下配置log4j会因为ejb无法得知由webapp类加载器加载的classes而有一些自己的特点(ejb和webapp用的类加载器不相同)。除非你的包和应用使用的相同类加载器加载ejb和webapp.下面我为说明这一点举个例子。

  我们会在我们安装的weblogic中部署一个非常简单的应用它包括jsp和ejb.这个ejb是个非常简单的ejb。当它被调用的时候会返回”hello world”

  example: why doesn't it work?

  例子:“它为什么不工作。“

  让我们用weblogic 的控制台安装.war文件和。ejb的.jar(ejb .jar file)文件。当我们想要安装ejb的.jar文件的时候。我们会发现org.apache.log4j.logger找不到的错误。

  ejb的.jar文件无法从与它相对应的webapp的目录下的web-inf目录得到log4j的消息。因为ejb和webapp使用的是不的类加载器.甚至是我们将ejb和webapp打包到同一个ear文件中(.ear file)。我们还是得到错误信息。这是为什么?即使我们将ejb和webapp打包到ear文件中使用相同的类加载器。我们还没有告诉我们的ejb去那里访问log4j.jar文件。

  example: why it will work

  例子:为什么它工作了。

  这里有个升级后可以工作的ear文件(updated .ear file)让我们看看都做了那些改动。

  • 我将log4j.jar文件从webapp的lib目录下面一移到了外层目录。与.war和ejb.jar文件平级。这

  样使得.jar文件对ejb来讲是可见的。

  • 我更改的ejb.jar文件中的manifest.mf,增加一个条目,使他包含了指向log4j.jar的classpath

  (class-path: log4j.jar)

  这些更改已经可以使我们将这个应用部署到weblogic上。当我们用控制台部署的时候已经没有出错信息了。因为现在ejb可以访问log4j。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java