教育培训类网站开发,wordpress 标签 彩色,怎样在中国建设银行网站开通短信提醒,关键词优化排名首页转载自#xff1a;http://www.blogjava.net/Sunday/archive/2007/08/18/137860.html 现在java编程中经常碰到ClassCastException 错误#xff0c;ClassCastException 是 JVM 在检测到两个类型间的转换不兼容时引发的运行时异常。此类错误通常会终止用户请求。本模式试图为您提…转载自http://www.blogjava.net/Sunday/archive/2007/08/18/137860.html 现在java编程中经常碰到ClassCastException 错误ClassCastException 是 JVM 在检测到两个类型间的转换不兼容时引发的运行时异常。此类错误通常会终止用户请求。本模式试图为您提供了解和排除 ClassCastException 错误最常见成因的一些基本要素。 为什么发生此问题 在执行几乎任何子系统Web 容器、EJB、JCA、群集等的应用程序代码或 WebLogic Server 代码内均可能发生 ClassCastException。通过转换可以指示 Java 编译器将给定类型的变量作为另一种变量来处理。对基础类型和用户定义类型都可以进行转换。Java 语言规范定义了允许的转换其中的大多数可在编译时进行验证。不过某些转换还需要运行时验证。如果在此运行时验证过程中检测到不兼容JVM 就会引发 ClassCastException。 假设有一个 S 类型的对象我们想把它转换为 T 类型。 S s; ... T t (T) s; 如果存在以下情况上述转换就可能引发 ClassCastException
S 与 T 不兼容。规范规定“当应用程序代码尝试将某一对象转换为某一子类时如果该对象并非该子类的实例JVM 就会抛出 ClassCastException。”以下是一个示例代码执行该代码时将会引发此类错误 public class TestCCE { public static void main(String args[]) { Object obj new Object(); String s (String) obj; } } S 类型和 T 类型兼容但加载时使用了不同的 ClassLoader。
第二个原因实际上是这种错误最常见的原因。这种情况在诊断上有相当的难度而且需要对 Java 类加载以及 WebLogic 类加载体系结构方面的基础知识有一定程度的了解。 返回页首什么是 ClassLoader ClassLoader 是允许 JVM 查找和加载类的一种 Java 类。JVM 有内置的 ClassLoader。不过应用程序可以定义自定义 ClassLoader。应用程序定义新的 ClassLoader 通常有两个主要目的
自定义和扩展 JVM 加载类的方式。例如增加对新的类库网络、加密文件等的支持 划分 JVM 名称空间避免名称冲突。举例来说利用划分技术可同时运行同一应用程序的多个版本基于空间的划分。此项技术在应用程序服务器如 WebLogic Server内的另一个重要用途是启用应用程序热重新部署即在不重新启动 JVM 的情况下启动应用程序的新版本基于时间的划分。 ClassLoader 按层级方式进行组织。除系统 Boot ClassLoader 外其它 ClassLoader 都必须有父 ClassLoader。http://e-docs.bea.com/wls/docs81/programming/classloading.html (English) 中提供了对 WebLogic 类加载体系结构的说明。 理解类加载的关键 记住以下内容会有帮助
永远无法在同一 ClassLoader 中重新加载类“热重新部署”需要使用新的 ClassLoader。每个类对其 ClassLoader 的引用都是不可变的this.getClass().getClassLoader()在加载类之前ClassLoader 始终会先询问其父 ClassLoader委托模型。这意味着将永远无法重写“核心”类同级 ClassLoader 间互不了解由不同 ClassLoader 加载的同一类文件也会被视为不同的类即便每个字节都完全相同。这是 ClassCastException 的一个典型成因。可以使用 Thread.setContextClassloader(cl) 将 ClassLoader 连接到线程的上下文 诊断 通常可以在服务器的日志和/或客户端获得完整的 ClassCastException 堆栈跟踪。该堆栈应能使您对涉及的 WebLogic Server 子系统的情况有相当深入的了解。请根据这些信息确认该问题是否与某个已知 WebLogic Server 问题的情况相符。如果相符请使用相应的解决办法。 如果错误与所有已知问题的情况均不相符则需要做进一步探查。如果错误出现在您可以编辑和编译源代码的类中以下方法可能有助于您理解该问题。 假设出现错误的代码行类似于
oo f (Foo) bar.method(); 如果按照转换规则该转换应该有效但仍然引发了 ClassCastException则可能的情况是类“bar”和“Foo”是由不同的 ClassLoader 加载的。要验证这一点请像下面这样拆分该代码行
Object o bar.method(); System.err.println(The object o classloader is o.getClass().getClassLoader()); System.err.println(Class Foo class loader is Foo.class.getClassLoader()); Foo f (Foo) o; 典型的输出可能与此类似
The object Foo3e86d0 classloader is sun.misc.Launcher$AppClassLoaderb9d04 Class Foo classloader is weblogic.utils.classloaders.ChangeAwareClassLoader5998cb finder: weblogic.utils.classloaders.MultiClassFinder7c2528 下一步是探查为什么涉及了不同的 ClassLoader。请执行下列检查清单中的各项检查
检查应用程序打包情况并检查“Foo”是否是使用由不同 ClassLoader 加载的不同模块打包而成。在这方面众所周知的一个成因是 Web 应用程序的“prefer-web-inf-classes”功能请参阅已知的 WebLogic 问题 检查它正在使用的应用程序代码或某个框架代码是否更改了 WebLogic 线程的上下文 ClassLoader且在请求流程期间未将其还原。如果应用程序代码内有对Thread.setContextClassloader(cl) 的调用就可能存在这种情况。如果上述所有措施均无济于事请尝试将问题隔离在一个简单的、可重现的测试案例中然后联系 BEA 技术支持部门以做进一步探查。 已知的 WebLogic Server 问题 以下汇集了可导致 ClassCastException 错误的各种情况您在使用各种 WebLogic 子系统时可能会遇到这些情况。 小程序 有关该情况的完整说明请参考 http://e-docs.bea.com/wls/docs81/applets/usingapplets.html (English) 摘要如果小程序中的 WebLogic Server 客户端尝试从 ClassLoader 获取某些资源信息且一并使用了缓存标志和 codebase/bea_wls_internal/classes 标志就可能会抛出 ClassCastException。 解决方法 在将类路径 servlet 用作代码基时请不要使用“cache_option”和“cache_archive”一类的缓存选项。 使用缓存选项时请不要使用 /classes (ClasspathServlet) 做为代码基。如果要这样做请先使用归档实用程序打包客户端 JAR。 有关此限制的详细信息请参阅 http://developer.java.sun.com/developer/bugParade/bugs/4648591.html (English)。 JCA Connector 有关该情况的完整说明请参考 http://e-docs.bea.com/wls/docs81/notes/issues.html (English)。 摘要发出连接请求时WebLogic Server 会返回一个代理对象该对象通过资源适配器将连接对象封装后返回到客户端。WebLogic Server 使用该代理来提供一些功能帮助应用程序使用 WebLogic Server 的“J2EE 连接器体系结构”实现。这些功能包括 (1) 连接泄漏检测功能和 (2) 连接请求在启动使用该连接的全局事务之前发出时推迟 XAResource 登记。 如果将连接请求返回的连接对象向原始的 Connection 类进行了转换就可能发生 ClassCastException。导致该异常的对象不外乎在连接请求过程中(1) 资源适配器进行转换时或 (2) 客户端进行转换时。 在 WebLogic Server 8.1 SP2 中尝试检测由上述资源适配器情况 (1) 导致的 ClassCastException。如果服务器检测到该转换失败将关闭代理包装器功能并在连接请求期间返回连接对象不进行包装。服务器会记录一条警告消息说明代理包装器已被关闭。出现此类转换故障时连接泄漏检测和 XAResource 推迟登记功能也将被关闭但当前在控制台监视中并不会就此给出任何指示。 WebLogic Server 尝试以使用容器管理的安全性的客户端身份检测 ClassCastException。如果要这样做则部署的资源适配器须定义安全性 Credential。 如果客户端在执行转换时发生 ClassCastException可按如下方式修改客户客户端代码 解决方法如果客户端将连接对象转换为 MyConnection而不是将 MyConnection 作为实现资源适配器的 Connection 接口的一个类请将该对象修改为一个扩展Connection 的接口。实现一个用于实现 MyConnection 接口的 MyConnectionImpl 类。 Servlet 动态重新加载 有关该情况的完整说明请参考 http://e-docs.bea.com/wls/docs81/jsp/reference.html (English) 摘要要在会话过程中动态重新加载 servlet 或 JSPservlet 会话中存储的对象必须是可序列化的。需要进行序列化是因为servlet 是使用新的 ClassLoader 重新加载的而这会导致此前加载的所有类旧版本 servlet 中的类与使用新的 ClassLoader 加载的所有类新版本 servlet 类发生不兼容的情况。这种不兼容会导致 servlet 返回 ClassCastException 错误。 使用 Prefer-web-inf-classes 功能 有关该情况的完整说明请参考 http://e-docs.bea.com/wls/docs81/programming/classloading.html (English) 摘要weblogic.xml Web 应用程序部署描述符包含一个 prefer-web-inf-classes 元素container-descriptor 元素的子元素。缺省情况下此元素设置为 False。如果将此元素设置为 True则不遵循 ClassLoader 委托模型从而使 Web 应用程序中的类定义的加载顺序优先于更高级别的 ClassLoader 中的类定义。这样 Web 应用程序就可使用其自己版本的第三方类该类也可能是 WebLogic Server 的一部分。请参阅 weblogic.xml Deployment Descriptor Elements (English)。 使用该功能时必须注意不要混淆使用 Web 应用程序的类定义创建的实例与使用服务器的定义创建的实例。如果混淆了此类实例就会发生 ClassCastException。 群集在 http 会话中存储包含 EJBObject 的自定义对象 - CR102119 摘要可序列化的自定义对象会包装 EJBObject对 EJB 的引用。该自定义对象存储在 http 会话中。会话复制时这种设计就会导致 ClassCastException。 解决方法在以后版本的 WebLogic Server 中将彻底解决该问题。目前的解决办法是在包装器内存储 EJB 句柄而不是 EJBObject。群集Failover 后使用 http 会话中的 EJB 句柄 - CR187062 摘要在群集中分别部署 webApp 和 EJB。EJB 句柄 包装在可序列化的自定义对象中而该对象存储在 http 会话中。Failover 后通过句柄访问 EJB 就会发生 ClassCastException。 解决方法在同一个 ear 文件中包装 webApp 和 EJB。该问题存在于 WLS 8.1sp2 中目前正在等待更正。 需要更多帮助 如果您已经理解这个模式但仍需要更多帮助您可以 在 http://support.bea.com/ 上查询 AskBEA例如使用“ClassCastException”以查找其它已发布的解决办法。在 http://forums.bea.com/ 上向 BEA 的某个新闻组提出更详细具体的问题。 如果这还不能解决您的问题并且您拥有有效的技术支持合同您可以通过登录以下网站来打开支持案例http://support.bea.com/。