如何欺骗 Java 服务提供者 API (jaxp)
-
25-09-2019 - |
题
我有一个小程序需要调用JAXP,具体来说 SAX解析器工厂. 。现在,正如您从 Javadoc 中看到的,这在内部使用了文档中的服务提供者机制 这里:
具体来说,如果它在我的任何应用程序 JAR 中都找不到名为 META-INF/services/javax.xml.parsers.SAXParserFactory
它会尝试从我的应用程序代码库中获取它。如果我的小程序部署如下:
<applet code="com.example.applets.MyApplet"
codebase="http://www.example.com/myapp/" archive="myapp.jar, dom4j.jar">
然后它会尝试向 http://www.example.com/myapp/META-INF/services/javax.xml.parsers.SAXParserFactory
我宁愿它不这样做,特别是因为我的小程序已签名,并且此附加 HTTP 调用会触发有关的警告 未签名的代码.
现在,显而易见的解决方案是像它所说的那样将 META-INF/services 文件放入我的应用程序 JAR 中,但我该如何做到这一点,同时仍然让它使用用户的 JAXP JRE 默认实现?或者,有没有办法说服小程序运行时查看 仅有的 在我的 JAR 文件中而不是在 codebase
对于那个文件?
笔记:我知道我也可以部署我自己的 JAXP-RI 副本,但这对于小程序来说是相当重量级的。
解决方案
禁用代码库查找:
<applet ...>
<param name="codebase_lookup" value="false">
</applet>
这 AppletClassLoader
检查布尔属性 sun.applet.AppletClassLoader.codebaseLookup
, ,可以通过设置上述参数来影响。方法 sun.applet.AppletPanel.init()
将读取参数并将其设置到 AppletClassLoader
. 。一旦禁用,AppletClassLoader 将停止对代码库中的类和资源进行远程查找,即由以下给出的 URL codebase="http://www.example.com/myapp/"
并且只查看档案和系统类路径。
笔记:我自己没有对此进行测试,但根据反汇编代码中的代码审查,我真诚地相信它可以工作。
它也记录在 JavaSE - 技术说明 - 插件开发人员指南 - 特殊属性:
代码库查找
当applet类加载器需要加载类或资源(例如,META-INF/services目录下的可插入服务提供者的配置文件)时,它首先在applet JAR文件中搜索所需的文件,然后从applet代码库中搜索。通常,小程序是通过存储在小程序 JAR 文件中的所有需要的类和资源来部署的。在这种情况下,代码库查找是不必要的。
如果类或资源无法从 applet JAR 文件中获得,则最好让类加载器失败,而不是尝试查找代码库。否则,必须连接到 applet 代码库才能搜索类或资源,并且可能会对 applet 运行时的性能产生影响。