为什么`java.lang.SecurityException:禁止包名:java`是必需的?

我创建了一个类“String”并将其放在包“java”中[实际上我想创建java.lang以查看classLoader加载哪个类

将类加载到JVM后,将不会再次加载相同的类(我重复,同一个类)

引自oreilly]。 但那件事后来,为什么我要上这门课
java.lang.SecurityException:禁止的包名: java

为什么安全性原因java不允许我在java包中有一个类? 如果没有这样的检查,怎么办?

永远不允许用户代码将类放入其中一个标准Java包中。 这样,用户代码就无法访问Java实现中的任何包私有类/方法/字段。 其中一些包私有对象允许访问JVM内部。 (我特别想到SharedSecrets 。)

首先,这些类型的限制适用于强制Java沙箱。 也就是说,在受信任的环境中运行不受信任的代码。 例如,在浏览器中的计算机(可信环境)上运行某个站点(您不一定信任)的applet。 目的是禁止不受信任的代码访问包私有的东西,这可能有助于它逃离沙箱。

通常,这些限制由SecurityManager强制执行,因此在命令行上运行自己的应用程序时不应该发生这些限制(除非您明确指定使用SecurityManager)。 当你控制环境时,你可以去编辑Java的rt.jar中的String.class定义(从技术上讲,你可以不知道许可证说的是什么)。 正如我所说,限制通常在SecurityManager中,但是关于java。*包的这个特殊规则是在ClassLoader类中。

回答你的问题:我的猜测是java。*检查是因为a)历史原因b)在Java核心的某个地方检查类的名称,例如:所有以java开头的类。* get特别待遇。

但是,请考虑即使您设法创建了一个名为java.lang.String的类,它也不会与Java核心定义的java.lang.String类相同。 它只是一个具有完全相同名称的类。 类标识不仅仅是类的名称,即使你真的很难理解,除非你真的使用ClassLoader。

因此,由java.lang包中的应用程序类加载器加载的类将无法访问核心java.lang包私有内容。

为了说明这一点,尝试使用main方法创建一个名为javax.swing.JButton的类并执行它。 你会得到一个java.lang.NoSuchMethodError: main 。 那是因为java在你的类之前找到了“真正的”JButton,而真正的JButton没有main方法。

在Java独立应用程序中,您可以通过使用reflection和setAccessible直接调用其中一个私有本机defineClassx方法来绕过此限制。

顺便说一下:核心java.lang.String保证在代码执行之前加载,因为它在任何地方都被引用,你不会先用你的用户代码到达那里。 在尝试加载类之前,JVM设置到一定程度,更不用说执行它了。

你不能拥有“java。*”包名。 这实际上是在Java核心中进行了硬编码,因此您甚至无法授予安全管理员权限来解决它(参见ClassLoader :: preDefineClass(…))

java是一个保留的包名。 只有JVM中的类可以驻留在此包中。

如果任何人都可以在Java包中编写,那么可能会导致库通过自己的实现任意替换核心Java类。 从破解核心Javafunction到执行恶意代码,这可能会产生很多想法。

如果程序可以使用木马版本覆盖JVM核心类,则程序可以绕过安全措施。 例如,String实际上在任何地方都使用。

ClassLoader.defineClass(..) javadoc:

…指定的类名不能以“java。”开头,因为“java。*包中的所有类只能由引导类加载器定义”

抛出:… SecurityException – 如果尝试将此类添加到包含由与该类不同的证书集签名的类的包,或者类名以“java。”开头。

可能在重构/补丁应用/等。 你已经添加到包名称’java’,它通常是一个包含包的文件夹。

所以你可以用结构结束:src-> main-> java-> java.com.yourpackage.name

它也可能发生在test:src-> main-> test-> java-> java.com.yourpackage.name

在IDE中validation它并删除“java”。 部分