如果我无法将第三方库包装起来,我经常使用这个技巧(在我们的类路径中有一些第三方相同的包和类名)来覆盖第三方库的功能。
在任何情况下,所有系统类都必须在客户端程序(我们的应用程序)加载之前加载到 jvm 中。这一切都是为了处理ClassLoader
,编译器允许它,因为它真的不太关心所有的类,但是在运行时,JVM类加载器会考虑这些东西,如果你看一下默认的源代码ClassLoader
(oracle jdk) , 你可以看到会有一个检查你不应该有任何包开头java.
private ProtectionDomain preDefineClass(String name,
ProtectionDomain protectionDomain)
{
...
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
...
}
即使使用著名的代码检测工具(例如javaassist
会限制这种行为),它们也会检查一个类是否可以检测Instrumentation.isModifiableClass
。
最后,这一切都取决于ClassLoader
实现,并且由于它必须遵守规范,您需要考虑从类路径到加载的类的顺序。