db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r1744989 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/services/bytecode/ testing/org/apache/derbyTesting/functionTests/tests/tools/ testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/
Date Sat, 21 May 2016 21:23:30 GMT
Author: kahatlen
Date: Sat May 21 21:23:30 2016
New Revision: 1744989

URL: http://svn.apache.org/viewvc?rev=1744989&view=rev
DERBY-6854: Make it possible to run Derby tests on early access
versions of JDK 9

JDK 9 will move the JDBC classes out of the boot class loader and into
the platform class loader (see JDK-8154189 in the OpenJDK bug

Derby has some test and debug code that assumes that the JDBC classes
live in the boot class loader.

1) Some tests create a new class loader in order to make the test load
the Derby classes afresh (SysinfoLocaleTest), or to test against a
different version of Derby (the upgrade tests). To achieve this, they
create a URLClassLoader which contains the Derby jar files they want
to test against, and set the parent of the URLClassLoader to null,
which means that the boot class loader is the parent.

Now that the JDBC classes are not on the boot class loader, this
URLClassLoader is not able to find the JDBC classes, and the tests
fail with NoClassDefFoundErrors when trying to load them.

This is fixed by setting the parent of the created URLClassLoader to
what java.sql.Connection.class.getClassLoader() returns. On JDK 8 and
earlier it returns null, so nothing changes there. On JDK 9 it returns
the platform class loader, which is capable of loading the JDBC

2) The org.apache.derby.impl.services.bytecode.d_BCValidate class
contains some debug code (only included in the sane jars) which runs
some sanity checks on the generated byte code. To do this, it accesses
the class loader of all the classes in the method signatures.

When getClassLoader() is called on JDBC classes, a RuntimePermission
is needed now. This was not the case before when the JDBC classes were
in the boot class loader, since Class.getClassLoader() does not check
for permissions if the class loader is null. Now this causes an
AccessControlException in tests that run with a security manager. The
tests actually grant the required permission to derby.jar, but the
call is not wrapped in AccessController.doPrivileged(), so it fails
because the permission is not granted to the test code.

The fix is to wrap the call to getClassLoader() in a doPrivileged()
block. Additionally, because RuntimePermission("getClassLoader") is
not a mandatory permission for derby.jar, we need to check if it
raises a security exception. d_BCValidate only needs the class loader
in order to check if it is the same class loader as d_BCValidate's own
class loader. Since Class.getClassLoader() does not require any
permissions if the class has the same class loader as the calling
class, we can conclude that the class loaders are different if a
security exception is raised.


Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/d_BCValidate.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/d_BCValidate.java?rev=1744989&r1=1744988&r2=1744989&view=diff
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/d_BCValidate.java
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/bytecode/d_BCValidate.java
Sat May 21 21:23:30 2016
@@ -22,11 +22,12 @@
 package org.apache.derby.impl.services.bytecode;
 import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import org.apache.derby.iapi.services.classfile.VMOpcode;
 import org.apache.derby.shared.common.sanity.SanityManager;
 import java.util.Hashtable;
-import org.apache.derby.iapi.services.loader.*;
-import org.apache.derby.iapi.services.context.*;
+import java.util.Objects;
  * Validate BC calls.
@@ -92,15 +93,23 @@ class d_BCValidate
 				// and members from classes loaded by the same class loader. Thus
 				// we try to fall into these categories to avoid having to grant
 				// permissions to derby jars for the function tests.
-				ClassLoader declareLoader = declaring.getClassLoader();
 				ClassLoader myLoader = d_BCValidate.class.getClassLoader();
-				boolean sameClassLoader = false;
-				if (declareLoader == myLoader)
-					sameClassLoader = true;
-				else if (declareLoader != null)
-					sameClassLoader = declareLoader.equals(myLoader);
+                boolean sameClassLoader;
+                try {
+                    ClassLoader declareLoader = AccessController.doPrivileged(
+                            (PrivilegedAction<ClassLoader>)
+                                    () -> declaring.getClassLoader());
+                    sameClassLoader = Objects.equals(myLoader, declareLoader);
+                } catch (SecurityException se) {
+                    // getClassLoader is not a mandatory permission for
+                    // derby.jar, so expect that it might fail. If it fails,
+                    // however, we know that it is not the same as myLoader,
+                    // since no permissions are needed for calling
+                    // getClassLoader() on a class that lives in the caller's
+                    // class loader.
+                    sameClassLoader = false;
+                }
 				String actualReturnType;

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/SysinfoLocaleTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/SysinfoLocaleTest.java?rev=1744989&r1=1744988&r2=1744989&view=diff
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/SysinfoLocaleTest.java
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/SysinfoLocaleTest.java
Sat May 21 21:23:30 2016
@@ -166,7 +166,13 @@ public class SysinfoLocaleTest extends B
         } else {
             urls = new URL[] { sysinfoURL };
-        URLClassLoader loader = new URLClassLoader(urls, null);
+        // Create a new class loader that loads the Derby classes afresh.
+        // Its parent (platformLoader) is a class loader that is able to
+        // load the JDBC classes and other core classes needed by the Derby
+        // classes.
+        ClassLoader platformLoader = java.sql.Connection.class.getClassLoader();
+        URLClassLoader loader = new URLClassLoader(urls, platformLoader);
         Class<?> copy = Class.forName(className, true, loader);
         Method main = copy.getMethod("main", new Class[] { String[].class });

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java?rev=1744989&r1=1744988&r2=1744989&view=diff
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java
Sat May 21 21:23:30 2016
@@ -181,10 +181,12 @@ public class UpgradeClassLoader
-        // Specify null for parent class loader to avoid mixing up 
-        // jars specified in the system classpath
-        ClassLoader oldVersionLoader = new URLClassLoader(url, null);
+        // Create a class loader which loads Derby classes from the specified
+        // URL, and JDBC classes and other system classes from the platform
+        // class loader.
+        ClassLoader oldVersionLoader =
+            new URLClassLoader(url, java.sql.Connection.class.getClassLoader());
         // DERBY-5316: We need to unload the JDBC driver when done with it,
         // but that can only be done if the DriverUnloader class lives in a

View raw message