Lit*_*van 5 java jvm classloader
我创建了一个库,它将 jar 直接加载到当前类路径中以启动其类之一。但注入的 jar 包含证书,所以我收到此错误:
java.lang.SecurityException: class "TestClass" signer information does not match signer information of other classes in the same package
Run Code Online (Sandbox Code Playgroud)
这很正常,但我无法摆脱它。这是正常的,因为两个不同的 jar 正在“冲突”,但是,我无法删除 JAR 的证书,因为它是第三方的。
那么,我可以禁用类证书检查吗?或者做一些事情来消除这个错误?
我想我需要覆盖该ClassLoader.checkCerts方法......但这很脏......
如果您尝试同时使用库的两个版本或两个实现(例如升级过程的一部分),那么您需要使用类加载器。
当必须解析一个类时,标准 Java 类加载器首先向加载它们的父类加载器询问该类,只有当父类加载器找不到该类时,它们才会尝试自己加载该类。这种“父类优先”的方法提供了安全性(因为加载的类不可能被覆盖)和稳定性(因为不能同时使用同一类的两个版本)。许多应用程序容器以不同的方式执行此操作,以便容器的实现不会影响其包含的应用程序的实现。
要在同一个应用程序中使用库的两个版本(例如 V1 和 V2),您需要至少使用两个类加载器。
在我看来,最干净的实现是从应用程序的标准类路径中省略所有提及 V1 和 V2 的内容。然后,您创建两个 ClassLoader 实例,一个用于 V1 及其依赖项,另一个用于 V2 及其依赖项。当任一版本运行时,另一个版本都不在类路径上,因此不存在冲突。遗憾的是,“干净”的实施并不总是可能的。
要让您的应用程序的大部分继续使用 V1,而其中的选定部分使用 V2,那么您需要使用一个类加载器,该加载器允许您覆盖加载顺序,以便其类优先于父级的类。我在https://github.com/kamranzafar/JCL找到了这样的实现。JCL 允许您设置类和资源的搜索顺序,并将自动为您创建代理,以便您无需使用反射来处理 V2 代码。
请注意,JCL 文档没有提到应该在配置之后和使用之前调用initialise其类上的方法。JarClassLoader
有几件事你不能使用类加载器做:
如果您尝试用不同的版本替换已签名的类,那么如果您可以这样做,就会破坏签名的精神,所以您不能这样做。这意味着您必须创建自己的未签名 jar。
如果您尝试替换加密库中的签名类,这可能会产生安全漏洞,因此您可能会发现需要使用自己的签名密钥对库进行签名,甚至需要使用 Oracle 认证的签名密钥,因为 JRE 非常挑剔关于谁可以加载加密类。