Jai
Jai

Reputation: 8363

Java: What happens when I create the same package as API

I'm curious what would happen if I create the exact same package that exists in an API that the project has (e.g. java.util from core Java API). Would the compiler give me an error or something?

If the compiler allows this, what would happen if I create a class with a name that the original API has?

Also, does that mean that package-private fields and methods are accessible if the compiler doesn't complain?

Upvotes: 0

Views: 141

Answers (3)

user207421
user207421

Reputation: 311052

You will be blocked by the class loader if the package name is prohibited, as in the case of java, or if you're trying to break into a package that is sealed in the JAR file it is distributed in.

Upvotes: 0

Jai
Jai

Reputation: 8363

I was curious enough that I did my own testing. I created java.util.concurrent and created a Test class with this method:

public static Object getResult(CompletableFuture<?> cf) {
    return cf.result;
}

Then I called it somewhere else in a main method. There is no compile error. Running that causes this:

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.util.concurrent at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662) at java.lang.ClassLoader.defineClass(ClassLoader.java:761) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)

So, it does seem like it has to do with classloader... or so I thought... Until I took a look at ClassLoader.preDefineClass():

// 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('.')));
}

So, it's stopping me because Java wants to protect all the packages starting with java!

I went and tried something else. I added javafx.scene package and another Test class with this method:

public static boolean getBoundsChange(Node n) {
    return n.boundsChanged;
}

Again, there is no compile errors, but it throws this at runtime:

Caused by: java.lang.IllegalAccessError: tried to access field javafx.scene.Node.boundsChanged from class javafx.scene.TestNode at javafx.scene.TestNode.getBoundsChange(TestNode.java:7) at testFX.start(testFX.java:29) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863) at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326) at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294) at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) ... 1 more

Seems like Java does protect against these, but does so only at runtime.

I created another interface in javafx.scene and just let it extend Consumer<T>. I can use it just like the original Consumer<T>, so there is nothing stopping me from using that package for my new classes.

Upvotes: 3

urgentx
urgentx

Reputation: 3931

Java packages are backed by folders on the file system, therefore you cannot create a copy of a package as it would just be the same folder.

There is nothing stopping you from creating a java.util package in your own project and using that. It would be a unique package name, and have nothing to do with the Java API.

Upvotes: -1

Related Questions