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.