为什么我能够重新创建java.lang包和类?

Sur*_*tta 37 java packages java.lang

我只是玩包结构.令我惊讶的是,我可以通过使用该名称创建我的包和类名来绕过默认类.

例如:

我创建了一个名为java.langClass 的包Boolean.当我导入java.lang.Boolean它不是JDK的版本Boolean.这是我的.它只是显示了Objects每个java对象的方法.

为什么这样 ?为什么我被允许创建包java.lang?程序运行正常.

在此输入图像描述

另一个困惑是如果我创建一个Class带有名称Object并尝试运行该程序然后异常

java.lang.SecurityException: Prohibited package name: java.lang
    at java.lang.ClassLoader.preDefineClass(Unknown Source)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

为什么会这样?这是一个错误还是正常行为?

dur*_*597 36

java.lang类的限制是运行时限制,而不是编译时限.

JVM实际上专门提供了一种覆盖类的机制java.lang.您可以使用-Xbootclasspath命令行标志来执行此操作:

-Xbootclasspath:bootclasspath
指定以分号分隔的目录,JAR文件和ZIP存档列表,以搜索引导类文件.这些用于代替Java平台JDK中包含的引导类文件.

不应部署使用此选项来覆盖rt.jar中的类的应用程序,因为这样做会违反Java Runtime Environment二进制代码许可证.

-Xbootclasspath/a:path
指定以分号分隔的目录路径,JAR文件和ZIP存档,以附加到默认引导程序类路径.

-Xbootclasspath/p:path
指定要在默认引导程序类路径前添加的以分号分隔的目录,JAR文件和ZIP存档的路径.

不要部署使用此选项的应用程序来覆盖rt.jar中的类,因为这违反了Java Runtime Environment二进制代码许可证.

但是,正如我已经用粗体标记强调的那样,这样做违反了Java SE和JavaFX技术Oracle二进制代码许可协议:

D. JAVA技术限制.您不得创建,修改或更改被许可方的行为,或授权其创建,修改或更改以任何方式标识为"java","javax","javax"的类,接口或子包的行为. javafx","sun","oracle"或Oracle在任何命名约定中指定的类似约定.您不得重新分发附表1中列出的软件.

除了上述内容之外,您可以将任何您想要的课程添加到您想要的任何课程中 ; 它在JLS§13.3中有具体讨论:

13.3.包的演变

如果新类型不重用先前给予不相关类型的名称,则可以将新的顶级类或接口类型添加到包而不破坏与预先存在的二进制文件的兼容性.

如果新类型重用先前为不相关类型指定的名称,则可能会导致冲突,因为同一类加载器无法加载这两种类型的二进制文件.

顶级类和接口类型的更改分别不是公共的,并且不是公共类型的超类或超接口,只会影响声明它们的包中的类型.即使此处另有描述不兼容性,也可以删除或以其他方式更改此类型,前提是该包的受影响二进制文件一起更新.


Ash*_*til 5

回答SecurityException相关问题:

当您的类加载器调用defineClass方法遇到指定的类(您的"自定义类")名称中包含"java.*"时,SecurityManger会抛出此RuntimeException .

这是因为您在"java.*"包中定义了您的类,并且根据ClassLoader的文档,这是不允许的.

defineClass()

..

指定的名称不能以"java."开头,因为"java.*包中的所有类只能由引导类加载器定义.如果name不为null,则它必须等于由指定的类的二进制名称.字节数组"b",否则将抛出NoClassDefFoundError.

抛出:..

SecurityException - 如果尝试将此类添加到包含由与此类不同的证书集签名的类的包,或者名称以"java."开头.

对于您的测试,尝试创建java.test包并定义一个Custom类(名称无关紧要;比如Object..).在这种情况下,您将获得相同的SecurityException.

package java.test;

public class Test {

    public static void main(String[] args) {

        System.out.println("This is Test");
    }
}
Run Code Online (Sandbox Code Playgroud)