Подтвердить что ты не робот

Почему я могу повторно создать пакет java.lang и классы?

Я просто играю с структурой пакета. И к моему удивлению, я могу обойти классы по умолчанию, создав свой пакет и имя класса с этим именем.

Для ex:

Я создал пакет под названием java.lang, а Class - 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)

Почему такое поведение? это ошибка или нормальное поведение?

4b9b3361

Ответ 1

Ограничение на классы java.lang - это ограничение времени выполнения, а не время компиляции.

JVM фактически обеспечивает механизм переопределения классов в java.lang. Вы можете сделать это, используя флаг командной строки -Xbootclasspath:

-Xbootclasspath:bootclasspath
Указывает список каталогов, JAR файлов и ZIP-архивов, разделенных точкой с запятой, для поиска файлов классов загрузки. Они используются вместо файлов классов загрузки, включенных в платформу Java JDK.

Приложения, которые используют этот параметр для переопределения класса в rt.jar, не должны развертываться, потому что это сделает противоречит лицензии двоичного кода Java Runtime Environment.

-Xbootclasspath/a:path
Указывает путь, разделенный точкой с запятой, каталогов, файлов JAR и ZIP-архивов для добавления к пути класса начальной загрузки bootstrap.

-Xbootclasspath/p:path
Указывает путь, разделенный точкой с запятой, каталогов, JAR файлов и ZIP-архивов для добавления перед дорожкой класса начальной загрузки.

Не развертывайте приложения, которые используют этот параметр, чтобы переопределить класс в rt.jar, потому что этот нарушает лицензию двоичного кода Java Runtime Environment.

Однако, как я уже подчеркивал смелыми знаками, это является нарушением Лицензионного соглашения на двоичный код Oracle для Java SE и технологий JavaFX:

Д. ОГРАНИЧЕНИЯ ТЕХНОЛОГИИ JAVA. Вы не можете создавать, изменять или изменять поведение или разрешать своим лицензиатам создавать, изменять или изменять поведение классов, интерфейсов или подпакетов, которые каким-либо образом идентифицируются как "java", "javax", "javafx", "sun", "oracle" или аналогичное соглашение, указанное Oracle в любом обозначении условного обозначения. Вы не должны распространять Программное обеспечение, указанное в Приложении 1.

Помимо вышесказанного, вы можете добавить любой класс, который вы хотите, в нужные вам пакеты; он специально обсуждался в JLS §13.3:

13.3. Эволюция пакетов

Новый класс верхнего уровня или тип интерфейса может быть добавлен в пакет без нарушения совместимости с ранее существовавшими двоичными файлами, если новый тип не повторно использует имя, ранее заданное для несвязанного типа.

Если новый тип повторно использует имя, ранее заданное для несвязанного типа, тогда может возникнуть конфликт, поскольку двоичные файлы для обоих типов не могут быть загружены одним и тем же загрузчиком классов.

Изменения класса и типов интерфейса верхнего уровня, которые не являются общедоступными и которые не являются суперклассом или суперинтерфейсом, соответственно публичного типа, влияют только на типы внутри пакета, в котором они объявлены. Такие типы могут быть удалены или иным образом изменены, даже если здесь несовместимы несовместимости, при условии, что поврежденные двоичные файлы этого пакета обновляются вместе.

Ответ 2

Ответ на вопрос SecurityException:

SecurityManger выбрасывает это исключение RuntimeException, в то время как ваш classloader, вызывающий метод defineClass и столкнувшийся с указанным классом (ваш "пользовательский класс" ), имеет в нем "java. *".

Это связано с тем, что вы определили свой класс в пакете "java. *" и документация ClassLoader это не разрешено.

defineClass()

..

Указанное имя не может начинаться с "java." , так как все классы в пакетах "java." могут быть определены только загрузчиком класса bootstrap. Если имя не равно null, оно должно быть равно двоичному имени класс, заданный байтовым массивом "b", иначе будет вызываться NoClassDefFoundError.

Броски:..

SecurityException. Если делается попытка добавить этот класс к пакету, который содержит классы, которые были подписаны другим набором сертификатов, чем этот класс, или если имя начинается с "java." .

Для тестирования попробуйте создать пакет java.test и определите один пользовательский класс (имена не имеют значения, например Object..). В этом случае вы также получите тот же SecurityException.

package java.test;

public class Test {

    public static void main(String[] args) {

        System.out.println("This is Test");
    }
}

Ответ 3

Это не ошибка.

Поведение beacause из:

Когда Java Virtual Machine (JVM) пытается загрузить наш класс, он распознает его имя пакета как недопустимое и, таким образом, генерируется SecurityException. SecurityException указывает, что произошло нарушение безопасности, приложение не может быть выполнено.                  Открытый класс SecurityException                  extends RuntimeException Брошенный диспетчером безопасности, чтобы указать на нарушение безопасности.

используйте другое имя пакета, это не только пакет языка java.it охватывает весь пакет, который не дает разрешений для переопределения в классах сборки и пакетах java.

Изменяя это, мы можем создать или переопределить тот же пакет и класс:

а/j2ee.core.utilities/SRC/орг/NetBeans/модули/j2ee/ядро ​​/API/поддержка/Java/JavaIdentifiers.java б/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"));

}

Ответ 4

Ваша проблема с java.lang.Boolean как ваш Boolean Class, а не Object One, просто объяснить.

Класс Object - это корень всех других классов, которые вы можете найти, использовать или даже создавать. Это означает, что если у вас есть возможность переопределить его, не будет работать ни один класс, метод или то, что вы хотите использовать, поскольку каждый из них зависит от этого корневого класса.
Для Boolean Class это не булев тип, а класс для булевого типа. И поскольку от этого ничего не зависит, тогда можно переопределить его.
Лучший способ понять эту проблему - посмотреть на эту ссылку:
[ http://docs.oracle.com/javase/7/docs/api/overview-tree.html]
Вы заметите, что каждый вид пакета, содержащий все классы java, зависит от класса объектов.

Таким образом, исключение безопасности, с которым вы столкнулись, похоже на "спаситель жизни" для вашей программы.
Если я ошибаюсь в вашем вопросе, другие люди могут найти более подходящий ответ на него.:)