Can I create a package of my own that has the same name as a predefined package
in Java, such as java.lang?
If so, what would the results be? Wouldn't that enable me to access that package's protected members?
If not, what prevents me from doing so?
No - java.lang is prohibited. The security manager doesn't allow "custom" classes in the java.lang package and there is no way telling him to accept them.
You're right - own classes declared in the java.lang namespace would allow you to use protected methods and members of classes in that package, and this is definitly not wanted.
This compiles fine - but - try to execute it ;)
package java.lang;
public class EvilAsEvilCanBe {
public static void main(String[] args) {
System.out.println("hehe");
}
}
Any package name matching "java.*" is prohibited and a security exception will be thrown.
There are two things preventing you.
1) The license agreement. "Note: Applications that use this option for the purpose of overriding a class in rt.jar should not be deployed as doing so would contravene the Java 2 Runtime Environment binary code license." http://download.oracle.com/javase/6/docs/technotes/tools/windows/java.html
2) You have to use the -Xbootclasspath:bootclasspath or add a lib/endorsed directory.
Some classes are not easily modified due to internal optimisations in the JVM e.g. you cannot add more than one method to Object to Sun/Oracle's JVM ;)
Related
I have a question about a sneaky way to gain access to package-access members that occurred to me. Specifically, I want to extend a class - let's call it com.acme.Foo - to add some functionality. This is pure addition: all current methods of Foo would be supported just by delegating to the superclass's method. However, there is no accessible constructor of Foo, so I can't extend the class and my implementation won't pass the "isA" test for being a Foo. There is no interface that expresses Foo-ness that I can use instead of inheritance.
This is where the sneaky thought occurred to me: Foo has a package-access constructor, so why not just create a package com.acme in my source folder and create an InheritableFoo class in that package:
package com.acme;
public class InheritableFoo extends Foo {
public InheritableFoo() {
super();
}
}
Now I can implement my extension to Foo by extending InheritableFoo, since that DOES have an accessible constructor.
This feels all wrong, and somehow unethical: I'm not respecting the decision the original programmer made when he or she decided to not expose a constructor for Foo. But it could be the case that they simply adopted the "deny everything until there's a reason for it" approach. Either way, is there anything fundamentally wrong with this idea? Am I going to cause myself problems in the future if I go this route, and if so, why?
You are correct regarding the fact that you can "sneak" in a class of your own into another package and get access to package restricted elements.
This will however only as long as the author of com.acme.foo distribute his code as source or an unsealed package. Should the author of this package distribute it as a sealed jar (which is quite common I believe) your approach will no longer work.
From Sealing Packages within a JAR File
Packages within JAR files can be optionally sealed, which means that
all classes defined in that package must be archived in the same JAR
file.
Only for example lets consider the class ClassFileAssembler from the sun.reflect package.
This class is a package local class:
class ClassFileAssembler implements sun.reflect.ClassFileConstants {...
So we can not use even its name ClassFileAssembler, we can not import it directly - it will lead to a compiler error.
However we can create a package named sun.reflect in our project and use the ClassFileAssembler name internally in this package - Java compiler will think that we are inside the ClassFileAssembler's package.
If so, why not to try to get a reference to a class object, i.e. ClassFileAssembler.class?
Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;
Unexpectedly this code leads to a run-time error: java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test.
However we still able to get the ClassFileAssembler class object:
Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");
It works fine and gives us a full class description.
So, the questions are:
1) What is the difference between techniques, how Class.forName0 retrieves reference to class object, and how .class does it?
2) Why do they have such different security checks?
3) What's the reason to protect .class reference in such way?
4) Do these techniques use different class loaders?
Class.forName don't care about whether a class is package local or not. It is when you attempt to use that class that access is checked. BTW if you do setAccessible(true) you can by pass these access restrictions.
The Reflection library allows you to do many things you cannot do in Java code. The Java has rules as to what you can and cannot do. e.g. you cannot set a final field outside a constructor or more than once. Note: the JVM doesn't have this restriction and at runtime you can use reflections to change it.
The reason this class is package local is to restrict access of the class to code outside this package. This doesn't mean you cannot access it if you really try, but it is less likely you will access it without serious thought being put into it. e.g. when I import classes in my IDE it often suggests classes from com.sun.* which are unlikely to be the right choice. (MY IDE can be set up to ignore these, but I often seem for find some new package I don't want)
The reason Reflections can do this is to support functionality such a Serialization. With Serialization you need to be able to serialize class outside the package of the Serialization library and obtain fields and reset them when deserializing. Reflections is also used by many Inversion of Control libraries though I suspect this is not what they had in mind when they design it.
If you check the javadoc of Class#forName, you will see that:
Note that this method does not check whether the requested class is accessible to its caller.
there is no difference. but you cannot access the static field .class of the package private (no modifier) class ClassFileAssembler.
everyone could access the Class instances, but the fields are protected.
in fact no one designed to protect .class reference this way, it's side effect of protecting other fields.
i dont think so.
I suspect the answer is no, but I want to check. If I have this structure in a Java application:
-package
-ClassA
-subpackage
-ClassB
-subsubpackage
-ClassC
I want package.subpackage.ClassB to have access to package.subpackage.subsubpackage.ClassC, but I don't want package.ClassA to have access to package.subpackage.subsubpackage.ClassC. Is there any way to enforce this?
No, the only access modifiers are:
public - global access
protected - package and subclass access
"package-private" (no modifier) - package access
private - class access only
protected and package-private doesn't recursively grant access to subpackages. In short, subpackages don't really have any relationship with their parent package except for the fact that they share the same name prefix.
Here is a Java Specification Request that (I believe) deals with this issue: http://jcp.org/en/jsr/detail?id=294
This was supposed to be implemented in the just recently released Java 7, but apparently has been forgotten.
The only way that you can get this to work is through the use of inner classes. And, honestly, if that doesn't work then maybe you should be asking, "What is so important about C that A shouldn't be able to instantiate it but B and at least one other class can?"
No, there isn't. A package name is not an hierarchical construct If we have a class
foo.bar.Application
then bar is not a child-package of foo. The package is foo.bar and there is no relation between foo and foo.bar, they are totally different packages (namespaces).
Making ClassC as an internal class for ClassB may solve your task.
No. The package hierarchy in Java has no effect on package visibility.
Things are either totally public or package-private.
There is no such thing as a "friend" package or a "parent" package here.
we can declare only one public file in a source file and file name must match the public class name
is there any reason to this restriction....
Well, it's not a compulsory restriction in Java. It's one that the Java Language Specification mentions as an option. From section 7.6 of the JLS:
When packages are stored in a file system (ยง7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
But basically it's there to encourage you to make your source easier to navigate. If you know the name of a public class, it's usually pretty easy to find the source code for it.
Yes, it's the specification of the Java language...
The reason is, that this is the convention. Also the classloader expects a class in a specific file. You can write your own classloader to avoid this restriction, but there is no good reason to do this. Everyone looking on your code will get confused. ;)
However, you can create "multiple" classes in one file by creating inner classes. I know, its not the same, but usually you should think about more important things than why there is only one class in one file.
It's there so that the compiler can find the source code of dependent classes.
#saravanan. I have executed some simple programs which show that just a single default class(ie a class with no access specifier) having the main method works well in java when u save the file name with the default class name.
To add on to the reason of naming the file with public class name, in a document I went through the details into this state that the JVM looks for the public class (since no restrictions and can be accessible from any where) and also looks for public static void main() in the public class .
This public class acts as the initial class from where the JVM instance for the java application( program) is begun.So when u provide more than one public class in a program the compiler itself stops you by throwing an error.
This is because later you can't confuse the JVM as to which class to be its initial class because only one public class with the public static void main(String args[]) is the initial class for JVM.
HOPE I have helped you in understanding JAVA programming naming better.
simply remember only that class would be public which has the main other files dont be public
I created a class "String" and placed that in package "java" [ actually i wanted to create java.lang to see which class is loaded by classLoader as
Once a class is loaded into a JVM, the
same class (I repeat, the same class)
will not be loaded again
quoted from oreilly ] . But that thing later, why on running this class i am getting
java.lang.SecurityException: Prohibited package name: java
For which security reason java is not allowing me to have a class in java package? What one could do if there will not be no such check?
User code is never allowed 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.)
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.
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.
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.
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.
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.
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.
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.
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.
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 is a reserved package name. Only classes inside the JVM can reside in this package.
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.
A program could bypass security measures if a program could override JVM core classes with trojan versions. For example, String is used practically everywhere.
From the 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
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. ".
Probably during refactoring/patch applying/etc. you have added to package name word 'java', which is usually a folder that contains packages.
So you could end with the structure:
src->main->java->java.com.yourpackage.name
It might also happens for test:
src->main->test->java->java.com.yourpackage.name
Verify it in your IDE and remove "java." part
An excerpt from java.lang.ClassLoader's preDefineClass method:
/* 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.
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.