为什么我能够重新创建 java.lang 包和类?
我只是在玩包结构.令我惊讶的是,我可以通过使用该名称创建我的包和类名来绕过默认类.
I am just playing with package structure. And to my surprise I can bypass the default classes by creating my package and class name with that name.
例如:
我创建了一个名为 java.lang
的包,Class 是 Boolean
.当我导入 java.lang.Boolean
时,它不是 JDK 的 Boolean
版本.这是我的.它只是显示了每个 java 对象都有的 Objects
的方法.
I created a package called java.lang
and Class is Boolean
. When I import java.lang.Boolean
it's not the JDK's version of Boolean
. It's mine. It's just showing the methods of Objects
which every object java have.
为什么会这样?为什么允许我创建包 java.lang
?并且程序运行良好.
Why so ? Why I am allowed to create the package java.lang
? And the program runs fine.
另一个困惑是,如果我创建一个名为 Object
的 Class
并尝试运行程序,那么就会出现异常
Another baffle is if I create a Class
with name Object
and try to runs the program then an exception
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)
为什么会出现这种行为?这是错误还是正常行为?
Why is this behaviour ? is this a bug or normal behaviour ?
推荐答案
java.lang
类的限制是运行时限制,而不是编译时限制.
JVM 实际上专门提供了一种机制来覆盖 java.lang
中的类.您可以使用 -Xbootclasspath代码>命令行标志:
The restriction on java.lang
classes is a runtime restriction, not a compile time one.
The JVM actually specifically provides a mechanism for overriding classes in java.lang
. You can do it using the -Xbootclasspath
command line flag:
-Xbootclasspath:bootclasspath
指定以分号分隔的目录、JAR 文件和 ZIP 归档列表以搜索引导类文件.这些用于代替 Java 平台 JDK 中包含的引导类文件.
-Xbootclasspath:bootclasspath
Specifies a semicolon-separated list of directories, JAR files, and ZIP archives to search for boot class files. These are used in place of the boot class files included in the Java platform JDK.
不应部署使用此选项来覆盖 rt.jar 中的类的应用程序,因为这样做会违反 Java 运行时环境二进制代码许可.
Applications that use this option for the purpose of overriding a class in rt.jar should not be deployed because doing so would contravene the Java Runtime Environment binary code license.
-Xbootclasspath/a:path
指定要附加到默认引导类路径的目录、JAR 文件和 ZIP 档案的分号分隔路径.
-Xbootclasspath/a:path
Specifies a semicolon-separated path of directories, JAR files, and ZIP archives to append to the default bootstrap class path.
-Xbootclasspath/p:path
指定一个以分号分隔的目录、JAR 文件和 ZIP 档案的路径,以添加到默认引导类路径的前面.
-Xbootclasspath/p:path
Specifies a semicolon-separated path of directories, JAR files, and ZIP archives to add in front of the default bootstrap class path.
不要部署使用此选项覆盖 rt.jar 中的类的应用程序,因为这违反了 Java 运行时环境二进制代码许可.
Do not deploy applications that use this option to override a class in rt.jar because this violates the Java Runtime Environment binary code license.
但是,正如我已经用粗体标记强调的那样,这样做违反了 Oracle 二进制代码许可协议适用于 Java SE 和 JavaFX 技术:
However, as I've already emphasized with bold marks, doing so is a violation of the Oracle Binary Code License Agreement for Java SE and JavaFX Technologies:
D.JAVA 技术限制.您不得创建、修改或更改其行为,或授权您的被许可人创建、修改或更改以任何方式标识为java"、"javax"、javafx"、sun"、oracle" 或 Oracle 在任何命名约定指定中指定的类似约定.您不得再分发附表 1 中列出的软件.
D. JAVA TECHNOLOGY RESTRICTIONS. You may not create, modify, or change the behavior of, or authorize your licensees to create, modify, or change the behavior of, classes, interfaces, or subpackages that are in any way identified as "java", "javax", "javafx", "sun", "oracle" or similar convention as specified by Oracle in any naming convention designation. You shall not redistribute the Software listed on Schedule 1.
除了上述之外,您还可以将您想要的任何类添加到您想要的任何包中;它在 JLS §13.3 中有专门讨论:
Apart from the above, you may add whatever class you want to whatever packages you want; it's specifically discussed in the the JLS §13.3:
新的顶级类或接口类型可以添加到包中而不会破坏与预先存在的二进制文件的兼容性,前提是新类型不会重用先前赋予无关类型的名称.
如果一个新类型重用了之前为不相关类型指定的名称,则可能会导致冲突,因为这两种类型的二进制文件无法由同一个类加载器加载.
If a new type reuses a name previously given to an unrelated type, then a conflict may result, since binaries for both types could not be loaded by the same class loader.
对非公共的顶级类和接口类型的更改,以及分别不是公共类型的超类或超接口的更改,仅影响声明它们的包中的类型.此类类型可能会被删除或以其他方式更改,即使此处以其他方式描述了不兼容性,只要该软件包的受影响二进制文件一起更新.
Changes in top level class and interface types that are not public and that are not a superclass or superinterface, respectively, of a public type, affect only types within the package in which they are declared. Such types may be deleted or otherwise changed, even if incompatibilities are otherwise described here, provided that the affected binaries of that package are updated together.
相关文章