to work with Java 9 Jigsaw Uwe Schindler Apache Lucene PMC & - - PowerPoint PPT Presentation

to work with java 9 jigsaw
SMART_READER_LITE
LIVE PREVIEW

to work with Java 9 Jigsaw Uwe Schindler Apache Lucene PMC & - - PowerPoint PPT Presentation

Challenges updating your code to work with Java 9 Jigsaw Uwe Schindler Apache Lucene PMC & Apache Software Foundation Member uschindler@apache.org https://www.thetaphi.de, http://blog.thetaphi.de @ThetaPh1 SD DataSolutions GmbH ,


slide-1
SLIDE 1

Challenges updating your code to work with Java 9 Jigsaw

Uwe Schindler

Apache Lucene PMC & Apache Software Foundation Member uschindler@apache.org https://www.thetaphi.de, http://blog.thetaphi.de @ThetaPh1

SD DataSolutions GmbH, Wätjenstr. 49, 28213 Bremen, Germany Tel: +49 421 40889785-0, https://www.sd-datasolutions.de

slide-2
SLIDE 2

What is this talk about?

  • Migrating your current project so it works

with Java 9 (Jigsaw)

  • Common pitfalls with Java 7 / Java 8

code, that just used to work

  • Not an introduction to the module system!
  • It does not show you how to “convert your

project” to be a module

slide-3
SLIDE 3

What changed in Jigsaw?

(module system)

  • Strong encapsulation:

– Code only sees classes from packages exported to your code – Private APIs are private – especially those in the JDK!

slide-4
SLIDE 4

What changed in Jigsaw?

(module system)

  • Strong encapsulation:

– Code only sees classes from packages exported to your code – Private APIs are private – especially those in the JDK!

  • Your code behaves as if it will be executed

with a security manager! 

slide-5
SLIDE 5

COMPILE TIME PROBLEMS

Examples

slide-6
SLIDE 6

Direct use of invisible/removed APIs

  • sun.misc.BASE64Encoder / -Decoder
  • sun.misc.Unsafe
  • com.sun.javafx.*

(http://openjdk.java.net/jeps/253)

slide-7
SLIDE 7

Direct use of invisible/removed APIs

  • sun.misc.BASE64Encoder / -Decoder
  • sun.misc.Unsafe
  • com.sun.javafx.*

(http://openjdk.java.net/jeps/253) If compiled with older Java version it will result in IllegalAccessError on Java 9

slide-8
SLIDE 8

Solution

slide-9
SLIDE 9

Solution

slide-10
SLIDE 10

Solution

slide-11
SLIDE 11

Solution

  • Scan your code with jdeps tool

– Maven plugin available – Works only with Java 8+

slide-12
SLIDE 12

Solution

  • Scan your code with jdeps tool

– Maven plugin available – Works only with Java 8+

  • Alternative: ForbiddenAPIs

– https://github.com/policeman-tools/forbidden-apis – jdk-non-portable or jdk-internal-* signatures – Maven/Gradle/Ant plugin for Java 6+

slide-13
SLIDE 13

Solution

  • Scan your code with jdeps tool

– Maven plugin available – Works only with Java 8+

  • Alternative: ForbiddenAPIs

– https://github.com/policeman-tools/forbidden-apis – jdk-non-portable or jdk-internal-* signatures – Maven/Gradle/Ant plugin for Java 6+

slide-14
SLIDE 14

Solution

  • Scan your code with jdeps tool

– Maven plugin available – Works only with Java 8+

  • Alternative: ForbiddenAPIs

– https://github.com/policeman-tools/forbidden-apis – jdk-non-portable or jdk-internal-* signatures – Maven/Gradle/Ant plugin for Java 6+

  • Won’t help if reflection was used!
slide-15
SLIDE 15

REFLECTION

Examples

slide-16
SLIDE 16

Reflection “hacks”

  • Clever people use reflection to access

private / internal Java APIs:

slide-17
SLIDE 17

Reflection “hacks”

  • Clever people use reflection to access

private / internal Java APIs:

– No compile-time dependency on Oracle JDK – Sometimes needed to access private members, e.g. “sun.misc.Unsafe” instance

slide-18
SLIDE 18

Reflection “hacks”

slide-19
SLIDE 19

Reflection “hacks”

  • Downside: Static

analysis can’t help

slide-20
SLIDE 20

Reflection “hacks”

  • Downside: Static

analysis can’t help

  • Much worse: No

correct error handling (if APIs are missing/incompatible)!

slide-21
SLIDE 21

Brokeness around the world

slide-22
SLIDE 22
  • People use setAccessible()

everywhere to break into internal APIs

Brokeness around the world

slide-23
SLIDE 23
  • People use setAccessible()

everywhere to break into internal APIs

– Almost no library does this correct

Brokeness around the world

slide-24
SLIDE 24
  • People use setAccessible()

everywhere to break into internal APIs

– Almost no library does this correct

  • People don’t wrap with

AccessController.doPrivileged()

Brokeness around the world

slide-25
SLIDE 25

Brokeness around the world

  • People forget to add correct try/catch:
slide-26
SLIDE 26

Brokeness around the world

  • People forget to add correct try/catch:

– e.printStackTrace() – throw new RuntimeException(e)

slide-27
SLIDE 27

Brokeness around the world

  • People forget to add correct try/catch:

– e.printStackTrace() – throw new RuntimeException(e) – …inside static initializers!

slide-28
SLIDE 28

Brokeness around the world

  • People forget to add correct try/catch:

– e.printStackTrace() – throw new RuntimeException(e) – …inside static initializers!

  • No alternative solution:
slide-29
SLIDE 29

Brokeness around the world

  • People forget to add correct try/catch:

– e.printStackTrace() – throw new RuntimeException(e) – …inside static initializers!

  • No alternative solution:

– static initializer breaks – NoClassDefFoundError forever!

slide-30
SLIDE 30

What’s wrong with Jigsaw?

#ReflectiveAccessToNonExportedTypes #AwkwardStrongEncapsulation

  • New since build 148 of Java 9
  • Prevents reflective access to any class

from Java runtime

slide-31
SLIDE 31

What’s wrong with Jigsaw?

#ReflectiveAccessToNonExportedTypes #AwkwardStrongEncapsulation

  • New since build 148 of Java 9
  • Prevents reflective access to any class

from Java runtime

#AwkwardStrongEncapsulation: A non-public element of an exported package can still be accessed via the AccessibleObject::setAccessible method

  • f the core reflection API. The only way to strongly

encapsulate such an element is to move it to a non-exported package. This makes it awkward, at best, to encapsulate the internals of a package that defines a public API.

slide-32
SLIDE 32

What’s wrong with Jigsaw?

#ReflectiveAccessToNonExportedTypes #AwkwardStrongEncapsulation

  • New since build 148 of Java 9
  • Prevents reflective access to any class

from Java runtime

slide-33
SLIDE 33

What does no longer work?

slide-34
SLIDE 34

What does no longer work?

  • Class.forName()

–on non-exported packages

slide-35
SLIDE 35

What does no longer work?

  • Class.forName()

–on non-exported packages

  • AccessibleObject

.setAccessible(true)

–on any public runtime class

slide-36
SLIDE 36

What does no longer work?

  • Class.forName()

–on non-exported packages

  • AccessibleObject

.setAccessible(true)

–on any public runtime class

  • Some exceptions:

–sun.misc.Unsafe

slide-37
SLIDE 37

Problems

  • No tool to detect reflective access to

private APIs with earlier Java versions during testing/compilation

  • Forbidden-APIs can disallow

AccessibleObject::setAccessible

slide-38
SLIDE 38

SOLUTIONS

What can I do?

slide-39
SLIDE 39

Run tests with SecurityManager!

(Apache Lucene, Apache Solr, Elasticsearch)

slide-40
SLIDE 40

Howto: Important patterns!

  • Add fallbacks for private APIs (try…catch

in static initializers)

  • Catch SecurityException AND

RuntimeException

slide-41
SLIDE 41

Howto: Important patterns!

  • Add fallbacks for private APIs (try…catch

in static initializers)

  • Catch SecurityException AND

RuntimeException

– InaccessibleObjectException extends RuntimeException 

slide-42
SLIDE 42

Howto: Important patterns!

  • Don’t fail in static initializers if you have

no workaround!

– Save error details while trying to initialize your private API hacks (Unsafe & Co.) – Use AccessController#doPrivileged – If consumer of your library calls a method using the hack, throw useful exception

slide-43
SLIDE 43

Early binding using MethodHandles

  • MethodHandles are bound early

– like javac is compiling and type-checking a method call

  • MethodHandles can be used to add

“programming logic” with if/then/else

– MethodHandles.guardWithTest() & Co.

  • No linkage errors possible at call time
slide-44
SLIDE 44

APACHE LUCENE’S MAPPEDBYTEBUFFER UNMAPPING

EXAMPLE

slide-45
SLIDE 45
slide-46
SLIDE 46

https://issues.apache.org/jira/browse/LUCENE-6989 https://bugs.openjdk.java.net/browse/JDK-4724038

slide-47
SLIDE 47
slide-48
SLIDE 48
slide-49
SLIDE 49
slide-50
SLIDE 50
slide-51
SLIDE 51
slide-52
SLIDE 52

Thank You!