JDK-8161269 : Regression in behavior of a null parent ClassLoader
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 9
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux_ubuntu,os_x
  • CPU: x86
  • Submitted: 2016-07-11
  • Updated: 2016-08-24
  • Resolved: 2016-07-13
Description
FULL PRODUCT VERSION :
[bin 698]$ $JAVA9_HOME/bin/java -version
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+126)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+126, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
[tmp 513]$ uname -a
Darwin Scotts-iMac.local 15.5.0 Darwin Kernel Version 15.5.0: Tue Apr 19 18:36:36 PDT 2016; root:xnu-3248.50.21~8/RELEASE_X86_64 x86_64



A DESCRIPTION OF THE PROBLEM :
A ClassLoader with a null parent ClassLoader appears to only have visibility into the java.base module. In Java 8 and earlier, such a ClassLoader would have visibility to all of the classes comprising the Java platform.

REGRESSION.  Last worked in version 8u92

ADDITIONAL REGRESSION INFORMATION: 
[bin 698]$ $JAVA9_HOME/bin/java -version
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+126)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+126, mixed mode)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
There is a complete sample app showing the problem available at https://github.com/RedHatJava9Testing/URLClassLoader.git.

1. git clone https://github.com/RedHatJava9Testing/URLClassLoader.git
2. cd URLClassLoader
3. $JAVA9_HOME/bin/javac -d bin src/*.java
4. [URLClassLoader 525]$ $JAVA9_HOME/bin/java -cp bin TestURLClassLoader
myModule=unnamed module @1efbd816, layer=null, md=null
myModule.classLoader=jdk.internal.loader.ClassLoaders$AppClassLoader@4b6995df, parent=jdk.internal.loader.ClassLoaders$PlatformClassLoader@66048bfd
rootURL=file:/Users/starksm/workspace/URLClassLoader/bin/
Loaded class: class JavaSqlUser, loader=java.net.URLClassLoader@402f32ff
JavaSqlUser.init, SqlDateUser.module:unnamed module @6d8a00e3, loader: java.net.URLClassLoader@402f32ff
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(java.base@9-ea/Native Method)
	at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(java.base@9-ea/NativeConstructorAccessorImpl.java:62)
	at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(java.base@9-ea/DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(java.base@9-ea/Constructor.java:453)
	at TestURLClassLoader.main(TestURLClassLoader.java:24)
Caused by: java.lang.NoClassDefFoundError: java/sql/Date
	at SqlDateUser.<init>(SqlDateUser.java:7)
	at JavaSqlUser.<init>(JavaSqlUser.java:10)
	... 5 more
Caused by: java.lang.ClassNotFoundException: java.sql.Date
	at java.net.URLClassLoader.findClass(java.base@9-ea/URLClassLoader.java:384)
	at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:486)
	at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:419)
	... 7 more


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
If you checkout the java8 branch, compile and run with a Java8 jdk you get the expected result:

1. git checkout java8
2. $JAVA8_HOME/bin/javac -d bin src/*.java
3. $JAVA8_HOME/bin/java -cp bin TestURLClassLoader
rootURL=file:/Users/starksm/workspace/URLClassLoader/bin/
Loaded class: class JavaSqlUser, loader=java.net.URLClassLoader@677327b6
Loaded instance: JavaSqlUser(SqlDateUser@7f31245a)

ACTUAL -
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(java.base@9-ea/Native Method)
	at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(java.base@9-ea/NativeConstructorAccessorImpl.java:62)
	at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(java.base@9-ea/DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(java.base@9-ea/Constructor.java:453)
	at TestURLClassLoader.main(TestURLClassLoader.java:24)
Caused by: java.lang.NoClassDefFoundError: java/sql/Date
	at SqlDateUser.<init>(SqlDateUser.java:7)
	at JavaSqlUser.<init>(JavaSqlUser.java:10)
	... 5 more
Caused by: java.lang.ClassNotFoundException: java.sql.Date
	at java.net.URLClassLoader.findClass(java.base@9-ea/URLClassLoader.java:384)
	at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:486)
	at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:419)
	... 7 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Available at https://github.com/RedHatJava9Testing/URLClassLoader.git
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
To achieve the same behavior as seen under Java8, one has to pass the new ClassLoader.getPlatformClassLoader() value as the parent ClassLoader rather than null.


Comments
This is not a bug as it has never been specified that all Java SE types be visible via the boot class loader. In JDK 9 then many non-core modules have moved to the platform (formerly extension) class loader - see JEP 200 and 261 for more details on this. See also this new section in the ClassLoader spec where it specifies that all platform classes are visible vis the platform class loader: http://download.java.net/java/jdk9/docs/api/java/lang/ClassLoader.html#builtinLoaders
13-07-2016

Checked this for 8u92, 9ea on Linux and Mac OS and could confirm the issue as reported by the submitter. Steps to reporudce: ************************* - Download the attached reproducer(URLClassLoader.7z) or git clone https://github.com/RedHatJava9Testing/URLClassLoader.git - cd URLClassLoader - git checkout java8 - javac -d bin src/*.java - java -cp bin TestURLClassLoader --------------------------------------------------------------------------------------------------------------------------------------------- Result: ********* OS : OS X El Capitan (Version 10.11.5), Linux Ubuntu 14.04 JDK: 8u92 b14 : Pass 9ea+126 : Fail ======================================================================================================================== Output (8u92,9ea+126): ======================================================================================================================== abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ java -version java version "1.8.0_92" Java(TM) SE Runtime Environment (build 1.8.0_92-b31) Java HotSpot(TM) 64-Bit Server VM (build 25.92-b31, mixed mode) abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ git checkout java8 Branch java8 set up to track remote branch java8 from origin. Switched to a new branch 'java8' abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ javac -d bin src/*.java abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ java -cp bin TestURLClassLoader rootURL=file:/media/sf_ora/ji/core-libs/URLClassLoader/bin/ Loaded class: class JavaSqlUser, loader=java.net.URLClassLoader@33909752 Loaded instance: JavaSqlUser(SqlDateUser@3d4eac69) ============================================================================================================== abhijit@abhijit-VirtualBox:/media/sf_ora/java$ java -version java version "9-ea" Java(TM) SE Runtime Environment (build 9-ea+126) Java HotSpot(TM) 64-Bit Server VM (build 9-ea+126, mixed mode) abhijit@abhijit-VirtualBox:/media/sf_ora/java$ corelibs abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs$ cd URLClassLoader/ abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ javac -d bin src/*.java abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ java -cp bin TestURLClassLoader rootURL=file:/media/sf_ora/ji/core-libs/URLClassLoader/bin/ Loaded class: class JavaSqlUser, loader=java.net.URLClassLoader@5b275dab Exception in thread "main" java.lang.reflect.InvocationTargetException at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(java.base@9-ea/Native Method) at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(java.base@9-ea/NativeConstructorAccessorImpl.java:62) at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(java.base@9-ea/DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(java.base@9-ea/Constructor.java:453) at TestURLClassLoader.main(TestURLClassLoader.java:26) Caused by: java.lang.NoClassDefFoundError: java/sql/Date at SqlDateUser.<init>(SqlDateUser.java:7) at JavaSqlUser.<init>(JavaSqlUser.java:12) ... 5 more Caused by: java.lang.ClassNotFoundException: java.sql.Date at java.net.URLClassLoader.findClass(java.base@9-ea/URLClassLoader.java:384) at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:486) at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:419) ... 7 more abhijit@abhijit-VirtualBox:/media/sf_ora/ji/core-libs/URLClassLoader$ ====================================================================================================================== Since it affects JDK 9ea, moving this up for dev to review.
13-07-2016