我正在玩包结构。令我惊讶的是,我可以通过使用该名称创建我的包和类名来绕过默认类。
例如:
我创建了一个名为<input/>
的包,类是java.lang
。当我导入Boolean
时,它不是JDK的java.lang.Boolean
版本。这是我的。它只显示每个对象java都有的Boolean
方法。
为什么这样?为什么我被允许创建包Objects
?程序运行正常。
另一个困惑是,如果我创建一个名为java.lang
的{{1}}并尝试运行程序然后异常
Class
为什么会出现这种情况?这是一个错误还是正常行为?
答案 0 :(得分:37)
java.lang
类的限制是运行时限制,而不是编译时间。 JVM实际上专门提供了覆盖java.lang
中的类的机制。您可以使用-Xbootclasspath
command line flag:
-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二进制代码许可证。
但是,正如我已经强调过大胆的标记,这样做违反了Oracle Binary Code License Agreement for Java SE and JavaFX Technologies:
d。 JAVA技术限制。 您不得创建,修改或更改被许可方的行为,或授权其创建,修改或更改以任何方式标识为&#34; java&#的类,接口或子包的行为。 34;,&#34; javax&#34;,&#34; javafx&#34;,&#34; sun&#34;,“oracle”或Oracle在任何命名约定中指定的类似约定。您不得重新分发附表1中列出的软件。
除上述内容外,您可以将您想要的任何课程添加到您想要的任何课程;它在JLS §13.3:
中具体讨论过13.3。包的演变
新的顶级类或接口类型可以添加到包中,而不会破坏与预先存在的二进制文件的兼容性,前提是新类型不会重用先前为不相关类型指定的名称。 < / p>
如果新类型重用先前为不相关类型指定的名称,则可能会导致冲突,因为同一类加载器无法加载这两种类型的二进制文件。
公共类型的非公共顶级类和接口类型的变化(分别不是超类或超级接口)仅影响声明它们的包中的类型。这些类型可能会被删除或以其他方式更改,即使此处另有描述不兼容,前提是该包的受影响二进制文件一起更新。
答案 1 :(得分:5)
回答SecurityException
相关问题:
当您的类加载器调用defineClass
方法并遇到指定的类(您的“自定义类”)名称中包含“java。*”时,SecurityManger会抛出此RuntimeException。
这是因为您在“java。*”包中定义了您的类,并且根据ClassLoader's documentation这是不允许的。
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");
}
}
答案 2 :(得分:4)
这不是Bug。
行为导致:
当Java虚拟机(JVM)尝试加载我们的类时,它会将其包名识别为无效,因此会抛出SecurityException。 SecurityException表示发生了安全违规,因此无法执行应用程序。 公共类SecurityException 扩展RuntimeException 安全管理员抛出指示安全违规行为。
请使用不同的软件包名称,不仅仅是java.it的语言包。覆盖所有软件包,不提供在构建类和java软件包中覆盖的权限。
通过更改此设置,我们可以创建或覆盖相同的包和类:
A / j2ee.core.utilities / SRC /组织/ netbeans的/模块/ J2EE /型芯/ API /载体/ JAVA / JavaIdentifiers.java B / j2ee.core.utilities / SRC /组织/ netbeans的/模块/ J2EE /型芯/ API /载体/ JAVA / JavaIdentifiers.java
**if (packageName.startsWith(".") || packageName.endsWith(".")) {// NOI18N
return false;
}
if(packageName.equals("java") || packageName.startsWith("java.")) {//NOI18N
return false;
}**
String[] tokens = packageName.split("\\."); //NOI18N
if (tokens.length == 0) {
return Utilities.isJavaIdentifier(packageName);
a/j2ee.core.utilities/test/unit/src/org/netbeans/modules/j2ee/core/api/support/java/JavaIdentifiersTest.java b/j2ee.core.utilities/test/unit/src/org/netbeans/modules/j2ee/core/api/support/java/JavaIdentifiersTest.java
assertFalse(JavaIdentifiers.isValidPackageName(" "));
assertFalse(JavaIdentifiers.isValidPackageName("public"));
assertFalse(JavaIdentifiers.isValidPackageName("int"));
assertFalse(JavaIdentifiers.isValidPackageName("java"));
assertFalse(JavaIdentifiers.isValidPackageName("java.something"));
}
答案 3 :(得分:1)
你的java.lang.Boolean作为你的布尔类而不是对象的问题很容易解释。
Object类是您可以查找,使用甚至创建的每个其他类的根。这意味着如果你能够覆盖它,那么你可以使用一个类,方法或任何你想要使用的东西,因为每个类都依赖于那个根类。
对于布尔类,它不是布尔类型,而是布尔类型的类。由于没有任何依赖它,因此可以覆盖它
理解这个问题的一个更好的方法是查看这个链接:
[[{3}}
你会注意到包含各种java类的每种包都依赖于Object类点。
所以你遇到的安全例外就像一个生命救星&#34;为您的计划。
如果我对你的问题不对,其他人可能会找到更恰当的答案。 :)