为什么需要 'java.lang.SecurityException: Prohibited package name: java'?

2022-09-01 21:43:11

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

一旦一个类被加载到JVM中,同一个类(我重复一遍,同一个类)将不会再次加载

引自oreilly] 。但是后来的事情,为什么在运行这个类时,我得到
java.lang.SecurityException:禁止的包名称:java

出于什么安全原因,java不允许我在java包中有一个类?如果没有这样的检查,人们能做些什么?


答案 1

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


答案 2

首先,这些类型的限制是为了强制实施Java沙箱。也就是说,在受信任的环境中运行不受信任的代码。例如,在浏览器中的计算机(受信任的环境)上从某个站点(您不一定信任该站点)运行小程序。其目的是禁止不受信任的代码访问包私有的东西,这可以帮助它逃离沙盒。

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

回答你的问题:我的猜测是java.*检查是因为a)历史原因b)在Java核心的某个地方有一个检查类的名称,比如:所有以java.*开头的类都会得到特殊对待。

但是,请考虑即使您设法创建了一个名为java.lang.String的类,它也与Java核心定义的java.lang.String不是同一类。它只是一个具有完全相同名称的类。类标识不仅仅是类的名称,尽管除非您真正使用ClassLoaders,否则这可能很难感知。

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

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

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

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