为什么需要'java.lang.SecurityException:禁止的包名:java'?
我创建了一个类“String”并将其放入包“java”[实际上我想创建java.lang以查看classLoader作为 将类加载到JVM后 同一班(我重复一遍,同一班) 将不会再次加载 引用自奥雷利]。但那件事以后,我为什么要上这门课呢为什么需要'java.lang.SecurityException:禁止的包名:java'?,java,security,Java,Security,我创建了一个类“String”并将其放入包“java”[实际上我想创建java.lang以查看classLoader作为 将类加载到JVM后 同一班(我重复一遍,同一班) 将不会再次加载 引用自奥雷利]。但那件事以后,我为什么要上这门课呢 java.lang.SecurityException:禁止的包名称:java 出于何种安全原因,java不允许我在java包中拥有类?如果没有这样的检查,我们该怎么办?用户代码永远不允许将类放入标准Java包中。这样,用户代码就无法访问Java实现中的任何包
java.lang.SecurityException:禁止的包名称:java
出于何种安全原因,java不允许我在java包中拥有类?如果没有这样的检查,我们该怎么办?用户代码永远不允许将类放入标准Java包中。这样,用户代码就无法访问Java实现中的任何包私有类/方法/字段。其中一些包私有对象允许访问JVM内部。(我特别想到的是
SharedSecrets
)如果程序可以用特洛伊木马版本覆盖JVM核心类,那么程序可以绕过安全措施。例如,字符串几乎在任何地方都被使用。java
是一个保留的包名。只有JVM中的类才能驻留在此包中
如果有人可以在Java包中编写代码,那么可能会导致库任意用自己的实现替换核心Java类。这可能会引发很多思考,从破坏核心Java功能到执行恶意代码。首先,这些类型的限制是为了强制执行Java沙箱。也就是说,在受信任的环境中运行不受信任的代码。例如,在浏览器中的计算机(受信任的环境)上从某个站点(您不一定信任)运行小程序。其目的是禁止不受信任的代码访问包私有内容,这有助于它逃离沙箱 通常,这些限制是由SecurityManager强制执行的,因此在命令行上运行自己的应用程序时不应发生这些限制(除非明确指定使用SecurityManager)。当您控制环境时,您可以直接在Java的rt.jar中编辑String.class定义(而且从技术上讲,您可以不确定许可是怎么说的)。正如我所说的,这些限制通常在SecurityManager中,但是关于java.*包的这个特殊规则在ClassLoader类中 回答你的问题:我猜java.*检查之所以存在是因为 a) 历史原因 b) 在Java核心的某个地方,有一个对类名称的检查,类似于:所有以Java开头的类。*得到特殊处理
但是,考虑到即使您创建了一个名为java. Lang.Stand的类,它也不会是java核心定义的JavaLang.Stand的类。它将只是一个名称完全相同的类。类标识不仅仅是类的名称,即使这很难理解,除非您真正使用类加载器
因此,由包java.lang中的应用程序类加载器加载的类将无法访问核心java.lang包私有内容 为了说明这一点,请尝试使用main方法创建一个名为javax.swing.JButton的类并执行它。您将得到一个java.lang.NoSuchMethodError:main
。这是因为java在类之前找到“真正”的JButton,而真正的JButton没有main方法
在Java独立应用程序中,您可以通过使用反射和setAccessible直接调用一个私有的本机defineClassx方法来绕过此限制
顺便说一句:核心java.lang.String保证在代码执行之前被加载,因为它到处都被引用,用户代码不会首先到达那里。JVM在尝试加载类之前就已经设置到一定程度,更不用说执行它了。您不能有“java.*”包名。这实际上是在Java核心中硬编码的,因此您甚至不能授予安全管理器权限来解决它(参见ClassLoader::preDefineClass(…)可能是在重构/补丁应用/etc期间。您已经在包名中添加了单词“Java”,它通常是一个包含包的文件夹 因此,您可以以以下结构结束: src->main->java->java.com.yourpackage.name 在测试中也可能发生这种情况: src->main->test->java->java.com.yourpackage.name 在IDE中验证它并从javadoc中删除“java.”部分: …指定的类名不能以“java.”开头,因为“java.*包”中的所有类只能由引导类装入器定义 及 抛出:…SecurityException-如果试图将此类添加到包含由不同于此类的证书集签名的类的包中,或者如果类名以“java”开头。“
摘自
java.lang.ClassLoader
的预定义类
方法:
/* Determine protection domain, and check that:
- not define java.* class,
- signer of this class matches signers for the rest of the classes in
package.
*/
private ProtectionDomain preDefineClass(String name,
ProtectionDomain pd)
{
...
// Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
// relies on the fact that spoofing is impossible if a class has a name
// of the form "java.*"
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException
("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
...
}
请注意,java.lang.ClassLoader
是一个抽象类,这意味着一个子类(比如,SecureClassLoader
)将实际实现它。但是,preDefineClass
方法是private
,因此它不能被子类覆盖
defineClass
由defineClass
方法调用,该方法是protectedfinal
。这意味着子类可以访问defineClass
,它们可以调用它,但它们不能更改它的实现。原则上我同意对风险的分析,但请注意,您只能如果您的类位于具有相同名称的包中并且由相同的类加载器加载,则访问包私有内容。不,这不是原因。用户代码可以通过反射API访问java
类中的私有成员。那么代码u呢