类装入异常

在开发应用程序或启动已安装的应用程序时,您遇到了哪种类型的类装入错误?

ClassCastException

在下列情况下会发生类强制转换异常,可以通过执行以下操作来更正该异常:

源对象的类型不是目标类(类型)的实例。
这是典型的类强制转换异常。可以通过执行以下操作来诊断强制转换语句的源对象是否不是目标类(类型)的实例:检查源对象类的类特征符,然后验证在它的祖代中是否未包含目标类并且源对象类是否与目标类不同。可以通过在代码中插入一条简单的 print 语句来获取类信息。例如:
System.out.println( source.getClass().getName() + “:” + target.getClass().getName() );
也可以使用 javap 命令。例如:
javap java.util.HashMap
Compiled from "HashMap.java"
public class java.util.HashMap extends java.util.AbstractMap
             implements java.util.Map,java.lang.Cloneable,java.io.Serializable {
装入了源对象(类)的类装入器与装入了目标类的类装入器不同。
假定源对象的类型是目标类的实例,当装入了源对象类的类装入器与装入了目标类的类装入器不同时,就会发生类强制转换异常。当目标类在 WebSphere® Application Server 运行时环境中的多个类装入器的类路径中可视时,可能会发生这种情况。要纠正此问题,请使用用来诊断类装入器问题的“搜索”和“按类名搜索”控制台页面:
  1. 单击故障诊断 > 类装入器查看器 > module_name > 搜索以访问“搜索”页面
  2. 对于搜索类型,选择类/包
  3. 对于搜索项,输入由两个类装入器装入的类的名称。
  4. 单击确定。此时将显示“按类名搜索”页,该页面列示了所有装入了该类的类装入器。

    如果列示了多个类装入器,那么表示多个类装入器装入了目标类。由于源对象是目标类的实例,所以装入了源对象类的类装入器与装入了目标类的类装入器不同。

  5. 返回到“类装入器查看器”页,检查类路径以确定两个不同类装入器装入该类的原因。
  6. 更正代码,以使该类只对适当的类装入器可视。
应用程序无法执行或错误地执行了 narrow 操作。
当应用程序解析远程企业 bean (EJB) 对象时,应用程序代码未执行必需的 narrow 操作,因此会发生类强制转换异常。在查询远程对象后,应用程序必须执行 narrow 操作。检查应用程序并确定它是否查询远程对象,如果是的话,将查询结果提交给 narrow 方法。

必须根据 EJB 2.0 编程模型来调用 narrow 方法。特别是,提交给 narrow 方法的目标类必须是 EJB 的精确的最底层派生接口。在 WebSphere Application Server 运行时环境中,这也会导致类强制类型转换异常。检查应用程序,确定提交给 narrow 方法的目标类是否是指定的 EJB 的超接口而不是精确的 EJB 类型;如果是的话,那么修改应用程序以使用精确的 EJB 接口来调用 narrow。

最后,如果在 narrow 操作期间发生类强制类型转换异常,那么验证 narrow 方法是否正应用于远程 EJB 查询结果,而不是本地企业 bean。不能对本地查询使用 narrow。检查应用程序或模块部署描述符,确保所收窄的对象不是本地对象。

ClassNotFoundException

在下列情况下会发生“找不到类”异常,可以通过执行以下操作来更正该异常:

该类在上下文类装入器的逻辑类路径中不可视。
找不到的类不在与当前线程相关的类装入器的逻辑类路径中。逻辑类路径是对类装入器调用装入操作时搜索的所有类路径的集合。要纠正此问题,请使用“搜索”页面来按类名和 Java™ 归档 (JAR) 名称进行搜索:
  1. 单击故障诊断 > 类装入器查看器 > module_name > 搜索以访问“搜索”页面
  2. 对于搜索类型,选择类/包
  3. 对于搜索项,输入找不到的类的名称。
  4. 单击确定。此时将显示“按类名搜索”页,该页面列示了所有装入了该类的类装入器。
  5. 查看该页面以确定列表是否列出了该类。
  6. 如果列表未列出该类,那么返回到“搜索”页。对于搜索项,输入类的 .jar 文件的名称;对于搜索类型,选择 JAR/Directory
  7. 单击确定。这就显示了“按路径搜索”页,该页面列示了所有包含该 JAR 文件的目录。

如果列表未列出该 JAR 文件,那么可能是该类不在逻辑类路径中、该类不可读或者已装入备用类。请将该类移至使其能够被装入的位置中。

应用程序不正确地使用了类装入器 API。
应用程序可以获取类装入器的实例并使用该类装入器调用 loadClass 方法,也可以使用该类装入器来调用 Class.forName(class_name, initialize, class_loader)。应用程序可能不正确地使用了类装入器应用程序编程接口 (API)。例如,类名不正确、该类在该类装入器的逻辑类路径中不可视或者使用了错误的类装入器。

要纠正此问题,请确定该类是否存在以及应用程序是否正确使用了类装入器 API。遵循该类在上下文类装入器的逻辑类路径中不可视中的步骤来确定是否已装入该类。如果尚未装入该类,那么尝试更正应用程序并确定是否能够装入该类。如果该类在类路径中并具有适当的许可权,并且未被另一个工厂类覆盖,那么检查用来装入该类的 API。

  1. 单击故障诊断 > 类装入器查看器 > module_name > 搜索以访问类装入器“搜索”页面
  2. 对于搜索类型,选择类/包
  3. 对于搜索项,输入类名。
  4. 单击确定。此时将显示“按类名搜索”页,该页面列示了所有装入了该类的类装入器。
  5. 查看该页面以确定列表是否列出了该类。
  6. 如果列表列出了该类,并且已抛出 ClassNotFound 异常,那么表示 .jar 文件或类不在正确的上下文中,或者在当前上下文中使用了不正确的 API 调用。
    如果列表未列出该类,那么返回到“搜索”页面并执行以下操作:
    1. 搜索生成了该异常的类;即,调用了 Class.forName 的类。
    2. 确定哪个类装入器装入了该类。
    3. 通过检查类装入器的类路径,确定类装入器能否访问或者能否装入找不到的类。
被依赖类不可视。
当类装入器 clsldr 装入类 cls 时,Java 虚拟机 (JVM) 将调用 clsldr 来装入 cls 所依赖的类。被依赖类在 clsldr 的逻辑类路径中必须可视,否则将发生异常。当用户使 WebSphere Application Server 类对 JVM 可视或者使应用程序类对 JVM 或对 WebSphere 扩展类装入器可视时,通常会发生这种情况。例如:
  • 类 A 依赖于类 B。
  • 类 A 对 WebSphere 扩展类装入器可视。
  • 类 B 在 WAR 模块类装入器的本地类路径中可视,但在 WebSphere 扩展类装入器类路径中不可视。

当 JVM 使用 WebSphere 扩展类装入器装入类 A 时,它会尝试使用同一个类装入器来装入类 B,这样,最终会生成“找不到类”异常。

要纠正此问题,请执行以下操作:

  1. 使特定于应用程序的类对适当的应用程序类装入器可视。
  2. 搜索找不到的类(类 B)。
  3. 如果类 B 在正确的位置中,那么在“类装入查看器”中搜索装入了被依赖类(类 A)的类
  4. 如果已装入该类,但抛出了 ClassNotFound 异常,那么表示 .jar 文件或类不在正确的上下文中或者在当前上下文中使用了错误的 API 调用。
    如果找不到任何类,那么执行以下操作:
    1. 搜索生成了该异常的类;即,调用了 Class.forName 的类。
    2. 确定哪个类装入器装入了该类。
    3. 通过检查类装入器的类路径,确定类装入器能否访问或者能否装入找不到的类。
  5. 确保调用者类(类 B)对 JVM 或 WebSphere 扩展类装入器可视。

NoClassDefFoundException

在下列情况下会发生“找不到类定义”异常,可以通过执行以下操作来更正该异常:

该类不在逻辑类路径中。
请参阅ClassNotFoundException,以了解更多信息。
无法装入该类。
无法装入类的原因各种各样。这些原因包括:无法装入被依赖类、被依赖类格式错误或者类的版本号不正确。

UnsatisfiedLinkError

在下列情况下会发生链接错误,可以通过执行以下操作来更正该错误:

用户操作导致了错误。

有几种用户操作会导致链接错误:

库扩展名对于平台来说不正确。

[Windows]库的动态链接库名为 library_name.dll

[AIX HP-UX Solaris]库名为 library_name.so 或者 library_name.a

传递给 System.loadLibrary 的参数不正确。

[Windows]要装入名为 Name.dll 的动态链接库,必须将 Name 传递给 loadLibrary 调用。

[AIX HP-UX Solaris]要装入名为 libName.solibName.a 的库,需将 libName 传递给装入库。

该库不可视。
最好的做法是使用 JVM 类装入器来查找或装入本机库。WebSphere Application Server 在启动时会打印 Java 库路径(java.library.path)。如果 JVM 类装入器将要装入该库,那么验证包含本机库文件的路径是否在 Java 库路径中。如果包含本机库文件的路径不在 Java 库路径中,那么将该路径追加到特定于平台的本机库环境变量中,或者追加到服务器进程定义的 java.library.path 系统属性中。

通常,Java 虚拟机使用类装入器 xxx 调用 findLibrary(),该类装入器装入了调用 System.loadLibrary() 的类。如果 xxx.findLibrary() 失败,Java 虚拟机就会尝试使用 JVM 类装入器来查找该库,JVM 类装入器将搜索 JVM 库路径。如果找不到该库,Java 虚拟机就会生成 UnsatisfiedLinkError 异常。

因此,如果 WebSphere 类装入器将要查找本机库 myNativeLib,那么该库在装入了调用 System.loadLibrary(myNativeLib) 的类的类装入器的 nativelibpath 中必须可视。在下列情况下,这种做法是有必要的或恰当的:

  • [z/OS]数据源提供程序的本机库在 WebSphere 扩展类装入器的 nativelibpath 中必须可视。在这种情况下,将包含本机库的路径添加到数据源提供程序配置的本机库路径设置中。
  • 共享库的配置包含本机库路径。由于共享库使得能够对特定于应用程序的库进行版本控制,所以,您应该考虑在共享库配置中指定共享库代码使用的任何本机库的路径。

确保正确的 WebSphere 类装入器装入了调用 System.loadLibrary() 的类,并确保本机库在本机库路径设置中可视。

[AIX HP-UX Solaris]
System.mapLibraryName 返回了错误的库文件。
装入共享库时,JVM 调用 mapLibraryName(libName) 来将 libName 转换为特定于平台的名称。在 AIX®、HP-UX 或 Solaris 操作系统上,此调用可能返回带有错误扩展名的文件名(例如,返回 libName.so 而不是 libName.a)。要对这种情况进行调试,请编写调用 System.mapLibraryName() 的程序并验证它是否返回了正确的文件名。
已装入本机库。
这种情况是由于下列任何一种错误导致的:
用户错误
检查是否对 System.loadLibrary 进行了多次调用,然后移除任何外部调用。
应用程序重新启动时出错
JVM 有一项限制,一次只能有一个类装入器可以装入本机库。在垃圾回收器从已停止应用程序中清理类装入器之前,如果应用程序重新启动,那么会导致错误。当装入本机库的类移动时,依赖于该本机库的所有类及其依赖性也必须移动。

要更正此条件,将本机库的装入移至不会重新装入的类装入器:

  1. 找到装入本机库或包含本机方法的所有应用程序类。
  2. 标识出步骤 1 中这些类的任何被依赖类,例如“日志记录包”。
  3. 创建与服务器关联的共享库或隔离式共享库。
  4. 将为步骤 1 和 2 中所述的类装入的 JAR 文件从应用程序移至步骤 3 中创建的共享库。
  5. 保存更改。
  6. 重新部署应用程序并重新运行方案。

在每个服务器生命周期中都装入一次限于服务器范围的库中的类,从而确保对每个 Java 虚拟机都装入一次应用程序所需的本机库,而不用考虑应用程序的生命周期。

使用了被依赖本机库。
JVM 类装入器必须能够找到或装入被依赖本机库。即,如果本机库 NL 依赖于另一个本机库 DNL,那么 JVM 类装入器必须能够在 Java 库路径中找到 DNL。这是因为 JVM 在装入 NL 时将运行本机代码;当它遇到对 DNL 的依赖关系时,JVM 本机代码只能调用 JVM 类装入器来解析依赖关系。WebSphere 类装入器无法装入被依赖本机库。

修改用于定义 Java 库路径的特定于平台的环境变量,以包括未解析的本机库所在路径。


指示主题类型的图标 参考主题



时间戳记图标 最近一次更新时间: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rtrb_classload_viewer
文件名:rtrb_classload_viewer.html