前边DGService框架在部署调用ejb的后台服务时,总是提示ClassNotFoundException这样的异常,所以花时间对虚拟机的类加载器的加载机制也研究了一下。
这里先简单的说一下类加载器的机制及其父类委托模式。
类加载器负责把类加载到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 实现的。
当处理类加载器时,父委托模式是一个需要理解的关键概念。它规定:类加载器在加载自己的类之前,可以委托先加载父类。父类加载器可以是客户化的类加载器或者引导类加载器。但是有一点很重要,类加载器只能委托自己的父类加载器,而不能是子类加载器(只能向上不能向下)。
扩展类加载器是应用程序类加载器的父亲。
如果应用程序类加载器需要加载一个类,它首先委托扩展类加载器,扩展类加载器再委托引导类加载器。如果父类加载器不能加载类,子类加载器就回在自己的库中查找这个类。基于这个特性,类加载器只负责它的祖先无法加载的类。
如 果类加载器加载一个类,这个类不是在类加载器树上的叶子节点上,就会出现一些有趣的问题。
类加载器的图示:
DGService中的后台服务热部署技术,就是通过在类加载器这一层做文章来实现的。我们的后台服务程序,是使用自定义的类加载器来加载的。但是,在后台服务中,调用ejb的时候,需要用到javax.naming.InitialContext这个类,而这个类是在jdk里的,自定义类加载器委托它的父类加载器去加载,父类加载器在jdk相关的包里找到了这个类,并进行了加载。这个时候javax.naming.InitialContext是被应用程序类加载器加载的。而在InitialContext调用了weblogic.jndi.WLInitialContextFactory这个类,基于被调用类和调用类使用同一类加载器这个原则,那么虚拟机会使用应用程序类加载器而不是我们在DGService里自定义的类加载器去加weblogic.jndi.WLInitialContextFactory这个类,但是weblogic.jndi.WLInitialContextFactory这个类是位于weblogic.jar包里的,也就是我们认为的第三方包,放在ext目录中。对于我们自定义的类加载器来说,ext目录下的jar包是位于类路径上的,但是对于应用程序类加载器来说,ext目录就不是类路径。所以,虚拟机再使用应用程序类加载器进行类加载并使用父类委托机制时,最终还是找不到这个类,所以ClassNotFoundException这个异常就被抛出了。还有一种情况就是发生ClassCastException,就是类型转换异常,这个大家都明白,把一种类型转换为强制转换为另外一种类型时,最有可能是向下转型的时候出现这种异常。但是,在DGService应用中,就是另外一种情况了,比如你把weblogic.jar设置了应用程序类加载器的类路径,而ejb调用的客户端放在了ext目录中,就会发生这种异常。检查代码肯定一点问题都没有,而且类型也不会错,但是确实报这种异常了,原因何在呢?其实,除了向下转型中出现这种异常,在不同类加载器加载的类之间进行转换,同样也会产生这样的异常。因为,ejb调用的相关代码的类是应用程序类加载器加载的,而ejb的客户端类是使用自定义类加载器加载的,这样就出现了ClassCastException异常。
所以,一个解决办法就是,我们把weblogic.jar以及ejb调用的客户端相关包放入lib目录下,并在startup.bat里指定类路径,也就是说,我们要把ejb调用的相关jar包设置为应用程序类加载器的类路径,这样就避免了ClassNotFoundException和ClassCastException异常。这样虽然解决了问题,但也带来了新的问题,也就是我们的jar包不能热部署,如果替换了,必须重新启动后台服务管理器。所以,最终的解决方案还是在我们自定义的类加载器下功夫,使用jndi技术来实现数据源,ejb等资源的加载,从而彻底解决ClassNotFoundException和热部署这一对矛盾。
分享到:
相关推荐
**EJB调用原理分析** Enterprise JavaBeans(EJB)是Java EE平台中用于构建分布式企业级应用的重要组件。EJB提供了服务器端的组件模型,允许开发者将业务逻辑封装在可重用的组件中,这些组件可以透明地运行在Java...
本文将深入探讨如何在WebSphere环境中远程调用EJB组件,同时介绍ejb3.0版本的一些关键特性,以及 ejb 开发实例和相关框架。 **一、EJB 3.0简介** EJB 3.0是EJB规范的一个重大改革,引入了更加轻量级和简化的设计,...
- Interceptors:拦截器可以插入到EJB调用链中,提供日志、事务管理和安全性等跨切面关注点。 5. EJB容器管理:Java EE应用服务器作为EJB容器,负责管理Bean的生命周期、事务、安全性和资源。这使得开发者能够专注...
WebLogic的类加载器体系遵循“父类加载器优先”原则,这意味着当一个类加载请求发生时,首先由父类加载器尝试加载,只有在其无法找到相应类时,才会将请求传递给子类加载器。WebLogic的主要类加载器包括Bootstrap类...
在EJB应用中,通常使用JPA(Java Persistence API)和ORM(Object-Relational Mapping)框架,如Hibernate,来处理数据持久化。EntityManager是JPA的核心接口,它提供了与数据库交互的能力,包括创建、查询、更新和...
EJB(Enterprise JavaBeans)是Java EE平台中的核心组件,用于构建可扩展的、安全的、事务处理的服务器端应用程序。本示例将探讨如何实现EJB的分布式远程调用,这是一种让不同网络节点上的软件组件能够相互通信的...
**EJB类加载器详解** ...该博客可能包含了作者在实际工作中遇到的问题、解决方案以及对EJB类加载器的深入分析。通过阅读这样的资源,你可以进一步提升对EJB类加载器的理解,并将其应用到你的项目中。
工具”中,我们可以推断这篇博客可能涉及了具体的代码示例和可能使用的工具,例如Eclipse或IntelliJ IDEA,用于开发和调试EJB3应用,或者可能提到了如JConsole或VisualVM这样的监控工具,用于查看和分析EJB3组件的...
在Java开发中,SSH、SSI、EJB以及Hibernate是几个重要的框架和技术,它们极大地提高了开发效率和代码质量。下面将详细解析这些框架的核心概念、作用以及如何整合使用。 1. **Struts1 & Struts2 (SSH)** Struts是...
当EJB3应用部署在JBoss服务器上,且调用者也在同一个环境中时,调用EJB相对简单。在这种情况下,Web应用可以作为客户端直接调用EJB。Web应用打包成WAR文件,并部署到JBoss。需要注意的是,由于Web应用和EJB都在同一...
- 创建一个Action类继承自`org.apache.struts.action.Action`,在这个类中实现具体的EJB调用逻辑。 4. **JNDI查找与远程调用** - 使用JNDI(Java Naming and Directory Interface)进行查找和获取EJB的远程接口...
综上所述,为了在Tomcat中成功调用EJB,你需要确保这些必要的jar文件被添加到WEB-INF/lib目录下,这样Tomcat在启动时能够找到并加载它们,从而提供EJB所需的功能和支持。正确的配置和使用这些库是确保EJB在Tomcat...
Struts2.0和EJB(Enterprise JavaBeans)是两种在Java开发中广泛使用的框架,它们各自解决不同的问题,但可以协同工作以构建强大的企业级应用程序。Struts2.0是一个MVC(Model-View-Controller)框架,主要用于处理...
EJB超时调用是指在EJB方法执行过程中,如果超过了预设的时间限制(即超时时间),系统会抛出异常并中断该方法的执行。这种情况通常发生在远程方法调用(Remote Method Invocation, RMI)或并发操作中,可能由于网络...
#### 二、JPA+EJB+JSF框架分析 JPA+EJB+JSF框架通常被应用于大型企业级应用中,它包含了持久化、业务逻辑以及表示层等多个方面的技术。 - **JPA (Java Persistence API)**:JPA是Sun官方提出的Java持久化规范,...
- **JNDI查找(Java Naming and Directory Interface, JNDI)**:客户端通过JNDI查找服务定位器,获取EJB的引用,然后进行调用。 3. **EJB生命周期**: - **创建(Create)**:客户端首次请求时,容器会创建一个...
类加载代理机制遵循“双亲委派模型”,即当一个类加载器接收到加载请求时,它首先会委托给其父类加载器尝试加载,只有当父类加载器无法完成加载时,才会自己尝试加载。然而,线程上下文类加载器提供了一种方式,可以...
调用EJB的客户端程序,通过远程接口方式调用