[
https://issues.apache.org/jira/browse/DERBY-6881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15219560#comment-15219560
]
Knut Anders Hatlen commented on DERBY-6881:
-------------------------------------------
Hi Bryan. Thanks for reviewing the patches.
Regarding the following line:
{code}
PrivilegedAction<ClassLoader> pa = () -> new URLClassLoader(new URL[0]);
{code}
Everything up to the equals sign is as before. That is, we're declaring a
variable pa of type PrivilegedAction<ClassLoader> and assigning a value to it.
What comes after the equals sign, is a so-called lambda expression. A lambda
expression can be used where an instance of an interface with a single abstract
method is expected. PrivilegedAction is such an interface (it has one method:
run()).
The lambda expression specifies how that method is implemented. It consists of
an argument list, an arrow (->) and then the function body. In this case, the
argument list is empty, so it's just a pair of parentheses (). Also, since the
method body consists of a single statement, we can use the shorthand syntax
where the method body has no curly braces around it and the "return" keyword is
left out. We could have chosen not to use the shorthand syntax and written this
instead:
{code}
PrivilegedAction<ClassLoader> pa = () -> {
return new URLClassLoader(new URL[0]);
});
{code}
One would often inline the lambda expression, rather than creating a helper
variable like I did in the patch. However, the obvious code
{code}
AccessController.doPrivileged(() -> new URLClassLoader(new URL[0]));
{code}
does not get accepted by the compiler. The reason is that there are two
variants of AccessController.doPrivileged(); one that takes a PrivilegedAction,
and one that takes a PrivilegedExceptionAction. The compiler cannot tell which
one we want to call without a little help. One way is to create a helper
variable of the desired type, like I did. Another way is to add a cast to give
the compiler more context:
{code}
AccessController.doPrivileged((PrivilegedAction) () -> new URLClassLoader(new
URL[0]));
{code}
If lambda expressions had been supported when the AccessController class was
added, I'm sure this clash and the resulting inconvenience would have been
avoided.
Lambda expressions can in many cases be used as a replacement for anonymous
inner classes. The most obvious advantage is that lambda expressions have much
less boilerplate than anonymous inner classes. It also slightly reduces the
footprint of the jar files. If you inspect the contents of derbyTesting.jar,
you'll see that the file
{{org/apache/derbyTesting/junit/ClassLoaderTestSetup$3.class}} has disappeared,
and no new class has been added to it.
This suggests that lambda expressions are not simply translated to a
corresponding anonymous inner class by the compiler. In fact, the JVM can
optimize this for us and produce code that performs better than the
corresponding anonymous inner class. For example, in this case, it can probably
see that the lambda expression is stateless, and produce a single instance that
is reused every time this code is executed. In contrast, the corresponding
anonymous class would have been instantiated every time, unless we added even
more boilerplate to cache a singleton instance manually. Not that we care much
about performance in the test code, but it's nice that the JVM can do this for
us automatically so that we don't have to do anything special in the places
where we do care about performance.
I haven't used these new features much myself, so everything above is probably
better and more correctly explained by the Java tutorial on lambda expressions:
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
> Test failures with JDK 9-ea b111
> --------------------------------
>
> Key: DERBY-6881
> URL: https://issues.apache.org/jira/browse/DERBY-6881
> Project: Derby
> Issue Type: Bug
> Components: Test
> Affects Versions: 10.13.0.0
> Reporter: Knut Anders Hatlen
> Attachments: d6881-classloader.diff, d6881-sed.diff
>
>
> With JDK 9-ea b111 there are a number of test failures.
> Tests that use ClassLoaderTestSetup fail because the context class loader no
> longer is a URLClassLoader, which causes a ClassCastException in the class
> loader magic performed by the test setup:
> {noformat}
> java.lang.ClassCastException: jdk.internal.loader.ClassLoaders$AppClassLoader
> (in module: java.base) cannot be cast to java.net.URLClassLoader (in module:
> java.base)
> at
> org.apache.derbyTesting.junit.ClassLoaderTestSetup$1.run(ClassLoaderTestSetup.java:53)
> at
> org.apache.derbyTesting.junit.ClassLoaderTestSetup$1.run(ClassLoaderTestSetup.java:50)
> at java.security.AccessController.doPrivileged(java.base@9-ea/Native
> Method)
> at
> org.apache.derbyTesting.junit.ClassLoaderTestSetup.makeClassLoader(ClassLoaderTestSetup.java:49)
> at
> org.apache.derbyTesting.junit.ClassLoaderTestSetup.setUp(ClassLoaderTestSetup.java:64)
> at junit.extensions.TestSetup$1.protect(TestSetup.java:20)
> at junit.extensions.TestSetup.run(TestSetup.java:25)
> at
> org.apache.derbyTesting.junit.BaseTestSetup.run(BaseTestSetup.java:58)
> {noformat}
> CollationTest, CollationTest2, LocalizedAttributeScriptTest and
> LocalizedDisplayScriptTest have failures, for example:
> {noformat}
> junit.framework.AssertionFailedError: Column value mismatch @ column 'ID',
> row 1:
> Expected: >4<
> Found: >6<
> ID,NAME
> -- ----
> [6, aacorn]
> [4, Acorn]
> [2, Ącorn]
> [0, Smith]
> [5, Śmith]
> [1, Zebra]
> [3, Żebra]
> at
> org.apache.derbyTesting.junit.BaseTestCase.newAssertionFailedError(BaseTestCase.java:1177)
> at org.apache.derbyTesting.junit.JDBC.addRsToReport(JDBC.java:1998)
> at
> org.apache.derbyTesting.junit.JDBC.assertRowInResultSet(JDBC.java:1497)
> at
> org.apache.derbyTesting.junit.JDBC.assertRowInResultSet(JDBC.java:1395)
> at
> org.apache.derbyTesting.junit.JDBC.assertFullResultSetMinion(JDBC.java:1257)
> at
> org.apache.derbyTesting.junit.JDBC.assertFullResultSet(JDBC.java:1168)
> at
> org.apache.derbyTesting.junit.JDBC.assertFullResultSet(JDBC.java:1125)
> at
> org.apache.derbyTesting.junit.JDBC.assertFullResultSet(JDBC.java:1083)
> at
> org.apache.derbyTesting.functionTests.tests.lang.CollationTest.checkLangBasedQuery(CollationTest.java:2055)
> at
> org.apache.derbyTesting.functionTests.tests.lang.CollationTest.testNorwayCollation(CollationTest.java:482)
> at
> org.apache.derbyTesting.junit.BaseTestCase.runBare(BaseTestCase.java:120)
> at
> org.apache.derbyTesting.junit.BaseJDBCTestCase.runBareOverridable(BaseJDBCTestCase.java:443)
> at
> org.apache.derbyTesting.junit.BaseJDBCTestCase.runBare(BaseJDBCTestCase.java:460)
> at junit.extensions.TestDecorator.basicRun(TestDecorator.java:24)
> at junit.extensions.TestSetup$1.protect(TestSetup.java:21)
> at junit.extensions.TestSetup.run(TestSetup.java:25)
> at junit.extensions.TestDecorator.basicRun(TestDecorator.java:24)
> at junit.extensions.TestSetup$1.protect(TestSetup.java:21)
> at junit.extensions.TestSetup.run(TestSetup.java:25)
> at
> org.apache.derbyTesting.junit.BaseTestSetup.run(BaseTestSetup.java:58)
> at junit.extensions.TestDecorator.basicRun(TestDecorator.java:24)
> at junit.extensions.TestSetup$1.protect(TestSetup.java:21)
> at junit.extensions.TestSetup.run(TestSetup.java:25)
> Caused by: junit.framework.AssertionFailedError: Column value mismatch @
> column 'ID', row 1:
> Expected: >4<
> Found: >6<
> at
> org.apache.derbyTesting.junit.JDBC.assertRowInResultSet(JDBC.java:1492)
> {noformat}
> And the stack trace deletion patterns in the Sed class seem to be missing out
> on some stack frames now, causing failures like this one in dblook_test and
> dblook_test_territory:
> {noformat}
> ********* Diff file derbyall/derbytools/dblook_test.diff
> *** Start: dblook_test jdk9-ea derbyall:derbytools 2016-03-29 14:16:38 ***
> 6511a6512
> > at java.io.FileInputStream.open0(java.base@9-ea/Native Method)
> Test Failed.
> {noformat}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)