Oracle Java存储过程中的类分辨率的混淆
-
10-09-2019 - |
题
我正在尝试在Oracle内使用第三方Java库。该库似乎与Oracle 10G服务器主机的JVM相同的1.4版本兼容,因为它在Oracle之外运行良好,因此我觉得我应该能够使其工作。该库最终会提出基于肥皂的HTTP请求,并且在Oracle运行时,我会得到类分辨率错误。
这是一个显示区别的行:
Class msgfact = Class.forName("com.sun.xml.messaging.saaj.soap.MessageFactoryImpl");
我试图用Loadjava实用程序将这些库注册到Oracle,我得到了我认为成功的结果:
C:\>loadjava -verbose -schema MYUSER -user MYUSER/MYPWD@dbinstance -force saaj-impl.jar
看起来所有内容都被加载了,我可以在该列表中看到此MessageFactoryImpl类。 But then I try to run this line of code from Oracle SQL (inside another class I wrote and loaded with loadjava), this line throws a ClassNotFoundException (java.lang.ClassNotFoundException: com/sun/xml/messaging/saaj/soap/MessageFactoryImpl )。
然后,我回去尝试在LoadJava命令行中添加“ - 溶解”开关。它的作用就像这些SAAJ课程正在注册,但它们无法正确解决。
我如何成功将这些SAAJ类进入Oracle,或者如果由于某种原因Oracle已经加载了这些类别,我该如何说服自己的代码成功使用现有类?
FWIW,我已经采取了步骤来确保授予适当的套接字权限,并且我的代码可以成功地向目标URL提出通用的HTTP请求。它只是使用图书馆的肥皂堆栈来实现它遇到麻烦。
编辑:这是我的LoadJava结果的示例。这似乎完全显示了什么是失败的,但是当这些特定类似乎在分辨率前的步骤中正确处理时,我感到困惑的是,为什么这些特定的类别无法解决。我在此处删除了大约80%的文件,但是还有其他类别显示相同的类分辨率问题。
arguments: '-verbose' '-schema' 'MYSCHEMA' '-user' 'MYSCHEMA/MYSCHEMA@actest' '-resolve' '-force' 'saaj-impl.jar' [snip] creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl creating : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl loading : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl [snip] resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/AttachmentPartImpl resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/Envelope resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/SOAPPartImpl could not be resolved resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/GifDataContentHandler resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/JpegDataContentHandler resolving: class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl could not be resolved errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/impl/EnvelopeImpl could not be resolved errors : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$1 ORA-29534: referenced object MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl could not be resolved skipping : class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$2 [snip] The following operations failed class MYSCHEMA.com/sun/xml/messaging/saaj/soap/EnvelopeFactory: resolution class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageFactoryImpl: resolution class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl: resolution class MYSCHEMA.com/sun/xml/messaging/saaj/soap/MessageImpl$1: resolution [snip] exiting : Failures occurred during processing
解决方案
首先,验证您要寻找的类的Oracle外面实际上是在该JAR文件中。我希望是,但是检查没有什么坏处。
然后,我将检查已加载哪些类以及它们是否具有有效状态。
SELECT object_name, dbms_java.longname(object_name), status
FROM user_objects
WHERE object_type='JAVA CLASS'
ORDER BY 1
如果有很多类,例如:
WHERE dbms_java.longname(object_name) LIKE '%MessageFactoryImpl'
如果类不存在,或者它的包裹名称错误,则问题是loadjava命令。
如果该类在那里,但其状态无效,请检查user_errors以查看错误。我不记得我是否在Oracle内完成了动态类加载,但是我记得静态链接会产生错误的错误,暗示该类是在真正存在但存在错误时不存在的。
LoadJava输出发布后的新信息
LoadJava输出似乎与您尝试在数据库中找到类的尝试不一致。如果已加载但未解决,则仍应列出它,但状态无效。
我得到了罐子,用空的模式自己尝试。该类负载,但无效,如预期的那样:
dev> select object_name, dbms_java.longname(object_name),status
2 from user_objects
3 where object_name like '%MessageFactoryImpl';
OBJECT_NAME
--------------------------------------------------------------------------------
DBMS_JAVA.LONGNAME(OBJECT_NAME)
--------------------------------------------------------------------------------
STATUS
-------
/3e484eb0_MessageFactoryImpl
com/sun/xml/messaging/saaj/soap/MessageFactoryImpl
INVALID
然后,我检查了课堂上的错误:
dev> alter java class "com/sun/xml/messaging/saaj/soap/MessageFactoryImpl" resolve;
dev> /
Warning: Java altered with compilation errors.
dev> show error
Errors for JAVA CLASS "/3e484eb0_MessageFactoryImpl":
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 ORA-29521: referenced name javax/xml/soap/MessageFactory could
not be found
0/0 ORA-29521: referenced name javax/xml/soap/SOAPMessage could not
be found
0/0 ORA-29521: referenced name javax/xml/soap/MimeHeaders could not
be found
0/0 ORA-29521: referenced name javax/xml/soap/SOAPException could not
be found
(假设至少尝试过一次分辨率,这些错误也将在User_errors中列出。)
因此,很明显,该类参考基础肥皂库中的类。您也必须加载 - 您做到了吗?
仅供参考,当我编写一些代码进行class.forname()调用时,我确实会获得classNotFoundException。由于架构中确实存在类对象,因此似乎是违反直觉的。但是,从Oracle中的类加载程序的角度来看,无效的类并不是真正的“存在”。为了使课程成为有效的甲骨文,必须能够解决其对其他类的所有参考。
其他提示
这是您第一次在数据库上执行Java吗?这是Hello World实施,以确保您的Oracle JVM运行正常,并且您拥有必要的权限。您说:“我的数据库模式,所以我可以做任何我想做的事 - 并不意味着您拥有适当的赠款。
SQL> create or replace and compile java source named "Hello" as
public class Hello{
public static String world() {
return "Hello World ";
}
};
/
Java created.
现在包装器功能
SQL> create or replace function Hello RETURN VARCHAR2
as LANGUAGE JAVA NAME 'Hello.world() return String';
/
Function created.
现在测试它
SQL> select Hello from dual;
HELLO
-----------------------------------
Hello World
做这个:
try
{
System.out.println("Class.forName returned: " +
Class.forName("com.sun.xml.messaging.saaj.soap.MessageFactoryImpl"));
}
catch(final Throwable ex)
{
ex.printStackTrace();
System.exit(1);
}
只是要使100AND10%确定它不会抛出以某种方式隐藏的例外,并且确实返回了空。如果仍然是这种情况,请告诉我(如果上述代码有效,但返回null)。
尝试#3 :-)(我不使用Oracle ...但这是一个整洁的问题...)
class.forname Oracle中的信息是否有帮助?
http://download.oracle.com/docs/cd/b14117_01/java.101/b12021/appover.htm#i1006547
这是一个班级加载程序问题,因此,解决方案与“真实的,非轨道”世界中发生的事情相同。
编辑...另一个尝试...
好的,再看一些...以下输出是什么:
System.out.println("vm vendor: " + System.getProperty("java.vendor"));
System.out.println("vm version: " + System.getProperty("java.version"));
System.out.println("class version: " + System.getProperty("java.class.version"));
我想知道类文件版本是否存在问题 - 类文件是否具有无法在Oracle VM上运行的版本?
类分辨率和负载是由VM处理的复杂操作。该规格中所述的这两个操作要使用的算法将为VM实施者打开。我的感觉是,在您的情况下,该分辨率仅在操作中仅检查课程本身的可用性,而在尝试有效加载类时,该分辨率稍后会失败(很可能是由于缺失的依赖性:加载类时,VM需要VM。至少解决所有直接引用其他类)。您必须确保Oracle所有类都可以使用,并对ORA-29534的Google进行快速搜索,显示了大量有这个问题的人(我很确定有人知道了)。
./alex
Saaj-impl.jar是Web Services开发人员包的SAAJ组件的一部分。据我所知,它对与Saaj一起发货的其他罐子具有依赖性,这绝对取决于saaj-api.jar和activation.jar。当然,Saaj-api.jar一定会依靠许多其他罐子。
就JWSDP 1.5而言,您可以在 JWSDP 1.5发行说明 有用。 JWSDP 1.6在Saaj I中有不同的罐子,发现JWSDP 2.0发行说明在这方面特别有用。顺便说一句,JWSDP 2.0将有不同的罐子要放置在类路径中;因此,问题的范围最终取决于您使用的saaj-impl.jar版本。
以防万一您可能需要它,在以下页面中,已经有一些文档可用于将肥皂客户罐加载到Oracle数据库中并利用它们。我认为这些与您的图书馆随附的SAAJ罐有所不同。