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.
For ex:
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.
Why so ? Why I am allowed to create the package java.lang
? And the program runs fine.
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 ?
No, java. lang package is a default package in Java therefore, there is no need to import it explicitly. i.e. without importing you can access the classes of this package.
lang package in Java. Provides classes that are fundamental to the design of the Java programming language. The most important classes are Object, which is the root of the class hierarchy, and Class, instances of which represent classes at run time.
Package names are written in all lower case to avoid conflict with the names of classes or interfaces. Companies use their reversed Internet domain name to begin their package names—for example, com. example. mypackage for a package named mypackage created by a programmer at example.com .
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
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.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
Specifies a semicolon-separated path of directories, JAR files, and ZIP archives to append to the default bootstrap class path.
-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.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.
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 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.
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:
13.3. Evolution of Packages
A new top level class or interface type may be added to a package without breaking compatibility with pre-existing binaries, provided the new type does not reuse a name previously given to an unrelated type.
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.
Answer to SecurityException
related question:
SecurityManger throws this RuntimeException while your classloader calling defineClass
method and encountered specified class(your "custom class") name has "java.*" in it.
This is because you defined your class in "java.*" package and as per ClassLoader's documentation this is not allowed.
defineClass( )
..
The specified name cannot begin with "java.", since all classes in the "java.* packages can only be defined by the bootstrap class loader. If name is not null, it must be equal to the binary name of the class specified by the byte array "b", otherwise a NoClassDefFoundError will be thrown.
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 name begins with "java.".
For your testing, try creating java.test
package and define one Custom class (names doesn't matter; like Object
..). In this case as well you will get same SecurityException.
package java.test;
public class Test {
public static void main(String[] args) {
System.out.println("This is Test");
}
}
This is not Bug.
Behaviour beacause of:
When the Java Virtual Machine (JVM) tries to load our class, it recognizes its package name as invalid and thus, a SecurityException is thrown. The SecurityException indicates that a security violation has occurred an thus, the application cannot be executed. public class SecurityException extends RuntimeException Thrown by the security manager to indicate a security violation.
please use different package name it not for only language package of java.it covers all package not gives permissions to override in build classes and packages of java.
By Changing this we can create or override same package and class:
a/j2ee.core.utilities/src/org/netbeans/modules/j2ee/core/api/support/java/JavaIdentifiers.java b/j2ee.core.utilities/src/org/netbeans/modules/j2ee/core/api/support/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"));
}
Your problem with java.lang.Boolean as your Boolean Class, and not the Object one is simple to explain.
The Object class is the root of every other classes you can find, use, or even create. Which means that if you could have the ability to override it, not a single class, method, or whatever you want to use would work, since every of them depends on that root class.
For the Boolean Class, it is not a boolean type, but a class for a boolean type. And since nothing depends on it, it is then possible to override it.
A better way to understand this problem, is to look at this link:
[http://docs.oracle.com/javase/7/docs/api/overview-tree.html]
You will notice that every kind of package, containing every kind of java classes, depends on the Object Class.
So the security exception you encountered is like a "life savior" for your program.
If I'm wrong about your question, other persons may find a more appropriate answer to it. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With