为什么需要`java.lang.SecurityException: Prohibited package name: java`?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3804442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
why `java.lang.SecurityException: Prohibited package name: java` is required?
提问by Rakesh Juyal
I created a class "String" and placed that in package "java" [ actually i wanted to create java.langto see which class is loaded by classLoader as
我创建了一个类“String”并将其放在包“java”中[实际上我想创建java.lang以查看 classLoader 加载哪个类作为
Once a class is loaded into a JVM, the same class (I repeat, the same class) will not be loaded again
一旦一个类被加载到 JVM 中,同一个类(我再说一遍,同一个类)将不会再次加载
quoted from oreilly ] . But that thing later, why on running this class i am getting
java.lang.SecurityException: Prohibited package name: java
引自oreilly]。但后来那件事,为什么在运行这个类时我得到
java.lang.SecurityException: Prohibited package name: java
For which security reason java is not allowing me to have a class in javapackage? What one could do if there will not be no such check?
出于哪个安全原因,java 不允许我在java包中有一个类?如果没有这种检查,人们可以做什么?
采纳答案by Chris Jester-Young
User code is neverallowed to put classes into one of the standard Java packages. That way, user code cannot access any package-private classes/methods/fields in the Java implementation. Some of those package-private objects allow access to JVM internals. (I'm thinking of SharedSecrets
in particular.)
永远不允许用户代码将类放入标准 Java 包之一中。这样,用户代码就无法访问 Java 实现中的任何包私有类/方法/字段。其中一些包私有对象允许访问 JVM 内部。(我SharedSecrets
特别想。)
回答by Bert F
A program could bypass security measures if a program could override JVM core classes with trojan versions. For example, String is used practically everywhere.
如果程序可以使用木马版本覆盖 JVM 核心类,则程序可以绕过安全措施。例如,String 几乎无处不在。
回答by Vivien Barousse
java
is a reserved package name. Only classes inside the JVM can reside in this package.
java
是保留的包名。只有 JVM 中的类可以驻留在这个包中。
If anyone could write in the Java package, that could result in libraries arbitrarily replacing core Java classes by their own implementations. That could result in a lot of thinks, from breaking core Java features to execution of malicious code.
如果任何人都可以在 Java 包中编写代码,那可能会导致库用自己的实现任意替换核心 Java 类。这可能会导致很多想法,从破坏核心 Java 功能到执行恶意代码。
回答by Sami Koivu
Firstly, these types of restrictions are in place to enforce the Java sandbox. That is, running untrusted code in a trusted environment. Such as running an applet from some site (that you don't necessarily trust), on your computer (the trusted environment) in your browser. The intent is to disallow untrusted code from gaining access to package-private stuff which could help it escape the sandbox.
首先,这些类型的限制是为了强制执行 Java 沙箱。也就是说,在受信任的环境中运行不受信任的代码。例如,在浏览器中的计算机(受信任环境)上从某个站点(您不一定信任)运行小程序。目的是禁止不受信任的代码访问包私有的东西,这可以帮助它逃离沙箱。
Normally these restrictions are enforced by the SecurityManager, so they shouldn't happen when you run your own application on the command-line (unless you explicitly specify to use a SecurityManager). When you control the environment, you could just go and edit the String.class definition inside the rt.jar of your Java (and you can, technically anyway, not sure what licensing says). As I said the restrictions are normally in the SecurityManager, but this particular rule about java.* packages is in the ClassLoader class.
通常这些限制是由 SecurityManager 强制执行的,因此当您在命令行上运行自己的应用程序时,它们不应该发生(除非您明确指定使用 SecurityManager)。当你控制环境时,你可以去编辑你的 Java 的 rt.jar 中的 String.class 定义(你可以,技术上无论如何,不确定许可是什么意思)。正如我所说,这些限制通常在 SecurityManager 中,但是这个关于 java.* 包的特殊规则在 ClassLoader 类中。
To answer your question: My guess is that java.* check is there because of a) historic reasons b) somewhere in the Java core there's a check on the name of the class, something like: All class that start with java.* get special treatment.
回答你的问题:我的猜测是 java.* 检查在那里是因为 a) 历史原因 b) 在 Java 核心的某个地方有一个对类名的检查,比如:所有以 java.* 开头的类得到特别待遇。
However, consider that even if you managed to create a class called java.lang.String, it would not be the same class as the java.lang.String defined by the Java core. It would just be a class with the exact same name. Class identity is more than just the name of the class, even though this can be tricky to perceive unless you really play with ClassLoaders.
但是,请考虑即使您设法创建了一个名为 java.lang.String 的类,它也不会与 Java 核心定义的 java.lang.String 类相同。它只是一个具有完全相同名称的类。类标识不仅仅是类的名称,尽管这可能很难理解,除非您真的使用类加载器。
So a class loaded by the application classloader in the package java.lang, would not have access to the core java.lang package-private stuff.
因此,应用程序类加载器在包 java.lang 中加载的类将无法访问核心 java.lang 包私有的东西。
To illustrate this, try to create a class called javax.swing.JButton with a main method and execute it. You'll get a java.lang.NoSuchMethodError: main
. That's because java finds the "real" JButton before your class, and the real JButton doesn't have a main method.
为了说明这一点,尝试使用 main 方法创建一个名为 javax.swing.JButton 的类并执行它。你会得到一个java.lang.NoSuchMethodError: main
. 那是因为java在你的类之前找到了“真正的”JButton,而真正的JButton没有main方法。
In a Java standalone application you might be able to go around this restriction by calling one of the private native defineClassx methods directly via use of reflection and setAccessible.
在 Java 独立应用程序中,您可以通过使用反射和 setAccessible 直接调用私有本机 defineClassx 方法之一来绕过此限制。
BTW: The core java.lang.String is guaranteed to be loaded before your code ever executes because it's referenced everywhere, you would not get there first with your user code. The JVM gets set up to a degree before ever even trying to load your class, let alone execute it.
顺便说一句:核心 java.lang.String 保证在您的代码执行之前加载,因为它在任何地方都被引用,您不会首先使用您的用户代码到达那里。JVM 甚至在尝试加载您的类之前就已设置到一定程度,更不用说执行它了。
回答by Jonathan Neufeld
You cannot have "java.*" package names. This is actually hard-coded in the Java core so you cannot even grant a security manager permission to work around it (cf. ClassLoader::preDefineClass(...))
你不能有“java.*”包名。这实际上是在 Java 核心中硬编码的,因此您甚至无法授予安全管理器权限来解决它(参见 ClassLoader::preDefineClass(...))
回答by szczepan.kurnyta
Probably during refactoring/patch applying/etc. you have added to package name word 'java', which is usually a folder that contains packages.
可能在重构/补丁应用/等期间。您在包名中添加了“java”一词,它通常是一个包含包的文件夹。
So you could end with the structure: src->main->java->java.com.yourpackage.name
所以你可以以结构结束:src->main->java->java.com.yourpackage.name
It might also happens for test: src->main->test->java->java.com.yourpackage.name
测试也可能发生这种情况:src->main->test->java->java.com.yourpackage.name
Verify it in your IDE and remove "java." part
在您的 IDE 中验证它并删除“java”。部分
回答by idelvall
From the ClassLoader.defineClass(..)
javadoc:
从ClassLoader.defineClass(..)
javadoc:
...The specified class name cannot begin with " java. ", since all classes in the " java.* packages can only be defined by the bootstrap class loader
...指定的类名不能以“ java. ”开头,因为“ java.* 包中的所有类只能由引导类加载器定义
and
和
Throws: ... SecurityException - If an attempt is made to add this class to a package that contains classes that were signed by a different set of certificates than this class, or if the class name begins with " java. ".
抛出: ... SecurityException - 如果尝试将此类添加到包含由与此类不同的证书集签名的类的包,或者如果类名以“java.”开头。
回答by M.S. Dousti
An excerpt from java.lang.ClassLoader
's preDefineClass
method:
java.lang.ClassLoader
的preDefineClass
方法摘录:
/* Determine protection domain, and check that:
- not define java.* class,
- signer of this class matches signers for the rest of the classes in
package.
*/
private ProtectionDomain preDefineClass(String name,
ProtectionDomain pd)
{
...
// Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
// relies on the fact that spoofing is impossible if a class has a name
// of the form "java.*"
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException
("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
...
}
Please note that java.lang.ClassLoader
is an abstract class, meaning that a subclass (say, SecureClassLoader
) will actually implement it. However, the preDefineClass
method is private
, so it cannot be overridden by a subclass.
请注意,这java.lang.ClassLoader
是一个抽象类,这意味着子类(例如, SecureClassLoader
)将实际实现它。但是,该preDefineClass
方法是private
,因此它不能被子类覆盖。
preDefineClass
is called by the defineClass
method, which is protected final
. This means defineClass
is accessible to subclasses and they can call it, but they won't be able to change its implementation.
preDefineClass
由defineClass
方法调用,即protected final
。这意味着defineClass
子类可以访问并且他们可以调用它,但他们将无法更改其实现。