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

时间:2015-08-20 11:15:27

标签: java packages java.lang

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

例如:

我创建了一个名为<input/>的包,类是java.lang。当我导入Boolean时,它不是JDK的java.lang.Boolean版本。这是我的。它只显示每个对象java都有的Boolean方法。

为什么这样?为什么我被允许创建包Objects?程序运行正常。

enter image description here

另一个困惑是,如果我创建一个名为java.lang的{​​{1}}并尝试运行程序然后异常

Class

为什么会出现这种情况?这是一个错误还是正常行为?

4 个答案:

答案 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;为您的计划。
如果我对你的问题不对,其他人可能会找到更恰当的答案。 :)