a post-apocalyptic sun.misc.unsafe world by christoph engelbert

113
http://www.superbwallpapers.com/fantasy/post-apocalyptic-tower-bridge-london-26546/ A Post-Apocalyptic sun.misc.Unsafe World

Upload: j-on-the-beach

Post on 12-Feb-2017

100 views

Category:

Software


4 download

TRANSCRIPT

http://www.superbwallpapers.com/fantasy/post-apocalyptic-tower-bridge-london-26546/

A Post-Apocalypticsun.misc.Unsafe

World

www.hazelcast.com@noctarius2k

Who’s that dude?• Chris Engelbert • Manager Developer Relations @Hazelcast

• Twitter-Senpai • Java-Passionist (10+ years)

• Performance • Garbage Collection • Benchmark Fairytales

DisclaimerThis talk is not going to be negative!

DisclaimerBut certain things are highly speculative

and APIs or ideas might change by tomorrow!

http://www.underwhelmedcomic.com/wp-content/uploads/2012/03/runningdude.jpg

sun.misc.Scissors

sun.misc.Unsafe - What you (don’t) know

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE

// Unsafe mechanicsprivate static final sun.misc.Unsafe U; private static final long QBASE; private static final long QLOCK; private static final int ABASE; private static final int ASHIFT; static { try { U = sun.misc.Unsafe.getUnsafe(); Class<?> k = WorkQueue.class; Class<?> ak = ForkJoinTask[].class; QBASE = U.objectFieldOffset (k.getDeclaredField("base")); QLOCK = U.objectFieldOffset (k.getDeclaredField("qlock")); ABASE = U.arrayBaseOffset(ak); int scale = U.arrayIndexScale(ak); if ((scale & (scale - 1)) != 0) throw new Error("data type scale not a power of two"); ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); } catch (Exception e) { throw new Error(e); } }}

example: java.util.concurrent.ForkJoinPool

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE• Used outside as well

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE• Used outside as well (good

// Deserialization public Object readObject(InputStream is) { SomeType element = unsafe.allocateInstance(SomeType.class); element.deserializeValues(is); return element;}

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE• Used outside as well (good, bad)

## A fatal error has been detected by the Java Runtime Environment:## SIGSEGV (0xb) at pc=0x00000001067314b5, pid=25244, tid=5891## JRE version: Java(TM) SE Runtime Environment (8.0_05-b13) (build 1.8.0_05-b13)# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.5-b02 mixed mode bsd-amd64 compressed oops)# Problematic frame:# V [libjvm.dylib+0x5314b5] Unsafe_SetNativeAddress+0x36## An error report file with more information is saved as:# /Users/noctarius/git/hazelcast-only.idea/hs_err_pid25244.log## If you would like to submit a bug report, please visit:# http://bugreport.sun.com/bugreport/crash.jsp#

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE• Used outside as well (good / bad)• Never intended for outside use

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE• Used outside as well (good / bad)• Never intended for outside use

sun.misc.Unsafe - What you (don’t) know

• Internal class (sun.misc Package)• Used inside the JVM / JRE• Used outside as well (good / bad)• Never intended for outside use• Used by popular:

• Applications• Frameworks• Libraries

MapDB

NettyHazelcast

Cassandra

Mockito

EasyMockJMock

Scala

Spock

Robolectric

Grails

GsonNeo4j

Apache IgniteApache Spark

Apache Kafka

Apache Wink

Apache Storm

Apache FlinkApache Continuum

Zookeeper

Dropwizard

Metrics (AOP)

Kryo

Byte Buddy

Hibernate

Liquibase

Spring Framework

Ehcache

OrientDB

Chronicle

Apache Hadoop

Apache HBase

GWTDisruptor

JRuby

AkkaAgrona

Aeron Simple Binary Encoding

XRebel

Presto

jol

ActivePivot

LWJGL

XAP

XStream

CapLogic

WildFly

Infinispan

MapDB

NettyHazelcast

Cassandra

Mockito

EasyMockJMock

Scala

Spock

Robolectric

Grails

GsonNeo4j

Apache IgniteApache Spark

Apache Kafka

Apache Wink

Apache Storm

Apache FlinkApache Continuum

Zookeeper

Dropwizard

Metrics (AOP)

Kryo

Byte Buddy

Hibernate

Liquibase

Spring Framework

Ehcache

OrientDB

Chronicle

Apache Hadoop

Apache HBase

GWTDisruptor

JRuby

AkkaAgrona

Aeron Simple Binary Encoding

XRebel

Presto

jol

ActivePivot

LWJGL

XAP

XStream

CapLogic

WildFly

Infinispan

sun.misc.Unsafe

is only supported on HotSpot JVMs anyways, isn’t it?

sun.misc.Unsafe

is only supported on HotSpot JVMs anyways, isn’t it?

No!

Language URL sun.misc.UnsafeAvian C++ https://github.com/ReadyTalk/avian Yes

BicaVM JavaScript https://github.com/nurv/BicaVM NoCacao C http://www.cacaojvm.org Yes

Excelsior JVM C / C++ ? http://www.excelsiorjet.com YesDalvik / ART / Android C / C++ https://source.android.com/source/index.html Yes

Graal mainly Java http://openjdk.java.net/projects/graal YesGCJ C / C++ https://gcc.gnu.org/java Yes

HaikuVM C http://haiku-vm.sourceforge.net NoIBM J9 C / C++ ? http://www.ibm.com/developerworks/java/jdk/index.html YesIcedTea C / C++ http://icedtea.classpath.org/wiki/Main_Page Yes

IKVM.NET C# http://www.ikvm.net YesJamiga C https://sourceforge.net/projects/jamiga2 NoJamVM C http://jamvm.sourceforge.net YesJatoVM C http://jatovm.org Yes

JikesRVM C microkernel, Java http://www.jikesrvm.org YesJNode C microkernel, Java http://www.jnode.org YesJVM.go Go https://github.com/zxh0/jvm.go Yes

JX C http://www4.cs.fau.de/Projects/JX/index.html NoKaffe C https://github.com/kaffe/kaffe Yes

NanoVM C http://harbaum.org/till/nanovm/index.shtml NoOpenJDK / Oracle / Zulu C / C++ http://openjdk.java.net Yes

RoboVM C / C++ / ObjC https://robovm.com YesSAPJVM C / C++ ? http://help.sap.com/saphelp_nwce10/helpdata/en/47/

dc90b4ef17452289f9128b8c2bbd77/content.htmYes

Waratek Multitenant JVM C / C++ ? http://www.waratek.com YesZing JVM C / C++ ? https://www.azul.com/products/zing Yes

Use Cases - The Good Ones!

Use Cases - The Good Ones!

• Low Latency, GC Overhead

Use Cases - The Good Ones!

• Low Latency, GC Overhead

Caution: Overly simplified!

Unsafe unsafe = findUnsafe();long baseAddress = unsafe.allocateMemory(8); class Point { long offsetX = 0; long offsetY = 4; int getX(long baseAddress) { return unsafe.getInt(baseAddress + offsetX); } int getY(long baseAddress) { return unsafe.getInt(baseAddress + offsetY); } }

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization

// Deserialization public Object readObject(InputStream is) { SomeType element = unsafe.allocateInstance(SomeType.class); element.deserializeValues(is); return element;}

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions

long baseAddress = unsafe.allocateMemory(Long.MAX_VALUE); unsafe.putInt(baseAddress + Long.MAX_VALUE - 4, Integer.MAX_VALUE);

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations

unsafe.compareAndSwapInt(this, offsetField, oldValue, newValue);unsafe.compareAndSwapLong(this, offsetField, oldValue, newValue);unsafe.compareAndSwapObject(this, offsetField, oldObject, newObject);

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout

class Point { long offsetX = 0; long offsetY = 4; }

offsetX

offsetY

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access

long versionFieldOffset = unsafe.objectFieldOffset(versionField);long version = unsafe.getLong(this, versionFieldOffset);unsafe.putLong(this, versionFieldOffset, 10L);

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access• Access to array elements with volatile semantics

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access• Access to array elements with volatile semantics

long base = unsafe.arrayBaseOffset(int[].class); long index = unsafe.arrayIndexScale(int[].class); unsafe.getIntVolatile(array, base + (index * 3));

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access• Access to array elements with volatile semantics• Custom memory fences

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access• Access to array elements with volatile semantics• Custom memory fences

unsafe.fullFence(); unsafe.storeFence(); unsafe.loadFence();

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access• Access to array elements with volatile semantics• Custom memory fences• Fast interaction with native code

Use Cases - The Good Ones!

• Low Latency, GC Overhead• Fast (de-)serialization• 64bit Memory regions• Atomic memory operations• Efficient memory layout• Fast field / memory access• Access to array elements with volatile semantics• Custom memory fences• Fast interaction with native code

long addr = unsafe.allocateMemory(50);copyBytes(addr, byteArray);nativeCall(addr);

Get Access

Get Access

Easy One (not working outside the JRE / JDK)

Unsafe unsafe = Unsafe.getUnsafe();

Get Access

The Ugly One

private static final Unsafe UNSAFE; static { try { Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafeField.setAccessible(true); UNSAFE = (Unsafe) theUnsafeField.get(Unsafe.class); } catch (Exception e) { // We need you! =( throw new Error(e); }}

Get Access

The Working One(at least for more than just HotSpot)

private static Unsafe findUnsafe() { try { return Unsafe.getUnsafe(); } catch (SecurityException se) { return AccessController.doPrivileged(new PrivilegedAction<Unsafe>() { @Override public Unsafe run() { try { Class<Unsafe> type = Unsafe.class; try { Field field = type.getDeclaredField("theUnsafe"); field.setAccessible(true); return type.cast(field.get(type)); } catch (Exception e) { for (Field field : type.getDeclaredFields()) { if (type.isAssignableFrom(field.getType())) { field.setAccessible(true); return type.cast(field.get(type)); } } } } catch (Exception e) { throw new RuntimeException("Unsafe unavailable", e); } throw new RuntimeException("Unsafe unavailable"); } }); }}

Get Access

The Tricky One

private static final Unsafe UNSAFE; static { try { Constructor<Unsafe> constructor = Unsafe.class.getDeclaredConstructor(); constructor.setAccessible(true); UNSAFE = constructor.newInstance(); } catch (Exception e) { // We need you! =( throw new Error(e); }}

Get Access

Does Any Of This Feel Right?

Weird!

No!

WAAAAAT!?!?

No!

Let me be blunt -- sun.misc.Unsafe must die in a fire. It is -- wait for it -- Unsafe. It must go. Ignore any kind of theoretical rope and

start the path to righteousness _*/now/*_. It is still years until the end of public updates to JDK 8, so we have /*years */to work this out

properly. But sticking our heads in the collective sands and hoping for trivial work arounds to Unsafe is not going to work. If you're using

Unsafe, this is the year to explain where the API is broken and get it straight....

Please help us kill Unsafe, kill Unsafe dead, kill Unsafe right, and do so as quickly as possible to the ultimate benefit of everyone.

Wed Apr 8 19:15:42 UTC 2015, OpenJFX Mailinglist, Donald Smith, Oracle

http://mail.openjdk.java.net/pipermail/openjfx-dev/2015-April/017028.html

Let me be blunt -- sun.misc.Unsafe must die in a fire. It is -- wait for it -- Unsafe. It must go. Ignore any kind of theoretical rope and

start the path to righteousness _*/now/*_. It is still years until the end of public updates to JDK 8, so we have /*years */to work this out

properly. But sticking our heads in the collective sands and hoping for trivial work arounds to Unsafe is not going to work. If you're using

Unsafe, this is the year to explain where the API is broken and get it straight....

Please help us kill Unsafe, kill Unsafe dead, kill Unsafe right, and do so as quickly as possible to the ultimate benefit of everyone.

Wed Apr 8 19:15:42 UTC 2015, OpenJFX Mailinglist, Donald Smith, Oracle

http://mail.openjdk.java.net/pipermail/openjfx-dev/2015-April/017028.html

Let me be blunt -- sun.misc.Unsafe must die in a fire. It is -- wait for it -- Unsafe. It must go. Ignore any kind of theoretical rope and

start the path to righteousness _*/now/*_. It is still years until the end of public updates to JDK 8, so we have /*years */to work this out

properly. But sticking our heads in the collective sands and hoping for trivial work arounds to Unsafe is not going to work. If you're using

Unsafe, this is the year to explain where the API is broken and get it straight....

Please help us kill Unsafe, kill Unsafe dead, kill Unsafe right, and do so as quickly as possible to the ultimate benefit of everyone.

Wed Apr 8 19:15:42 UTC 2015, OpenJFX Mailinglist, Donald Smith, Oracle

http://mail.openjdk.java.net/pipermail/openjfx-dev/2015-April/017028.html

Let me be blunt -- sun.misc.Unsafe must die in a fire. It is -- wait for it -- Unsafe. It must go. Ignore any kind of theoretical rope and

start the path to righteousness _*/now/*_. It is still years until the end of public updates to JDK 8, so we have /*years */to work this out

properly. But sticking our heads in the collective sands and hoping for trivial work arounds to Unsafe is not going to work. If you're using

Unsafe, this is the year to explain where the API is broken and get it straight....

Please help us kill Unsafe, kill Unsafe dead, kill Unsafe right, and do so as quickly as possible to the ultimate benefit of everyone.

Wed Apr 8 19:15:42 UTC 2015, OpenJFX Mailinglist, Donald Smith, Oracle

http://mail.openjdk.java.net/pipermail/openjfx-dev/2015-April/017028.html

Oracle created a new Taskforce

Oracle created a new Taskforce

K.U.T.T. - Kill Unsafe To Total death

Let me be blunt -- sun.misc.Unsafe must die in a fire. It is -- wait for it -- Unsafe. It must go. Ignore any kind of theoretical rope and

start the path to righteousness _*/now/*_. It is still years until the end of public updates to JDK 8, so we have /*years */to work this out

properly. But sticking our heads in the collective sands and hoping for trivial work arounds to Unsafe is not going to work. If you're using

Unsafe, this is the year to explain where the API is broken and get it straight....

Please help us kill Unsafe, kill Unsafe dead, kill Unsafe right, and do so as quickly as possible to the ultimate benefit of everyone.

Wed Apr 8 19:15:42 UTC 2015, OpenJFX Mailinglist, Donald Smith, Oracle

http://mail.openjdk.java.net/pipermail/openjfx-dev/2015-April/017028.html

So What’s Coming?

private static final Unsafe UNSAFE = findUnsafe();private static long VERSION_OFFSET = findVersionOffset();

// Updated through Unsafe only!private volatile long version = 0;

public long increment() { while(true) { long version = this.version; long newVersion = version + 1; if (UNSAFE.compareAndSwapLong( this, VERSION_OFFSET, version, newVersion)) {

return newVersion; } }}

Atomic Updates

Atomic Updates

private final AtomicLong version = new AtomicLong(0);

public long increment() { return version.incrementAndGet();}

Atomic Updates

private static final AtomicLongFieldUpdater<Record> VERSION = AtomicLongFieldUpdater.newUpdater(Record, "version");

// Updated through atomic field updater only! private volatile long version = 0; public long increment() { return VERSION.incrementAndGet(this); }

Atomic Updates

private static final VarHandle VERSION = findVersionVarHandle();// Updated through VarHandle only!private volatile long version = 0; public long increment() { return (long) VERSION.addAndGet(this, 1);}

Atomic Updates

public static VarHandle findVersionVarHandle() { try { return MethodHandles.lookup(). findFieldVarHandle(Record.class, "version", long.class); } catch (Exception e) { throw new Error(e); }}

Memory Management

public long memory() { long address = UNSAFE.allocateMemory(8); UNSAFE.putLong(address, Long.MAX_VALUE); return UNSAFE.getLong(address);}

Memory Management

public long memory() { ByteBuffer byteBuffer = ByteBuffer.allocateDirect(8); byteBuffer.putLong(0, Long.MAX_VALUE); return byteBuffer.getLong(0);}

Memory Management

public long memory() { ByteBuffer byteBuffer = ByteBuffer.allocateDirect(8); VarHandle bufferView = MethodHandles.byteBufferViewVarHandle(long[].class, true); bufferView.set(byteBuffer, 0, Long.MAX_VALUE); return bufferView.get(byteBuffer, 0); }

Memory Management

public long memory() { MemoryRegion region = MemoryRegion.allocateNative ("myname", MemoryRegion.UNALIGNED, Long.MAX_VALUE); VarHandle regionView = MethodHandles. memoryRegionViewVarHandle(long[].class, true); regionView.set(region, 0, Long.MAX_VALUE); return regionView.get(region, 0);}

Memory Management

public long memory() { MemoryRegion region = MemoryRegion.allocateNative ("myname", MemoryRegion.UNALIGNED, Long.MAX_VALUE); VarHandle regionView = MethodHandles. memoryRegionViewVarHandle(long[].class, true); regionView.set(region, 0, Long.MAX_VALUE); return regionView.get(region, 0);}

Memory Management

public long memory(long index) { try (Scope scope = new NativeScope()) { Pointer<Long> ptr = scope.allocate( NativeLibrary.createLayout(long.class), numElements); Reference<Long> ref = ptr.offset(index).deref(); ref.set(Long.MAX_VALUE); return ref.get(); }}

Memory Management

Deserialization

private static final Unsafe UNSAFE = findUnsafe();private static final long VALUE_OFFSET = findValueOffset();public String deserializeString() throws Exception { char[] chars = readCharsFromStream(); String allocated = (String) UNSAFE.allocateInstance(String.class); UNSAFE.putObjectVolatile(allocated, VALUE_OFFSET, chars); return allocated;}

Deserialization

public String deserializeString() throws Exception { char[] chars = readCharsFromStream().freeze(); ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory(); Constructor<String> constructor = reflectionFactory .newConstructorForSerialization(String.class, char[].class); return constructor.newInstance(chars);}

Interoperabilityextern c { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);} JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObj) { return getpid();} public class ProcessIdentifier { static { System.loadLibrary("processidentifier"); } public native void talk();}

Interoperability

interface LibC { void getpid();} public int call() { LibC c = LibraryLoader.create(LibC.class).load("c"); return c.getpid();}

Interoperability

public void call() { MethodType intType = MethodType.methodType(int.class); MethodHandle handle = MethodHandles .findNative(null, “getpid”, intType); return (int) handle.invokeExact();}

Value Types

value class Point { final int x; final int y; } // Create a Point instancePoint point = makeValue(1, 2);

Value Types

int[] values = new int[2];int x = values[0]; int y = values[1];

Value Types

int[] values = new int[2];int x = values[0]; int y = values[1];

Stack

var X

var Y

Value Types

int[] values = new int[2];int x = values[0]; int y = values[1];

Stack

var X

var Y

Stack Allocation!

Specialized Generics

class Box<any T> { void set(T element) { ... }; T get() { ... };}

Specialized Generics

class Box<any T> { void set(T element) { ... }; T get() { ... };}

Box<int> Box${T=int}.classBox<String> Box${T=java.lang.String}.classBox<RandomClass> Box${T=RandomClass}.class

Specialized Genericspublic void generics() { Box<int> intBox = new Box<>(); intBox.set(1); int intValue = intBox.get(); Box<String> stringBox = new Box<>(); stringBox.set("hello"); String stringValue = stringBox.get(); Box<RandomClass> box = new Box<>(); box.set(new RandomClass()); RandomClass value = box.get();}

Arrays 2.0int[] values = new int[Long.MAX_VALUE];

Arrays 2.0int[] values = new int[Long.MAX_VALUE];

Arrays.chop(T[] a, int newlength);

Arrays 2.0int[] values = new int[Long.MAX_VALUE];

Arrays.chop(T[] a, int newlength);

Box<String>[] ... = new Box<String>[];

Arrays 2.0int[] values = new int[Long.MAX_VALUE];

Arrays.chop(T[] a, int newlength);

Box<int>[] ... = new Box<int>[];

Arrays 2.0int[] values = new int[Long.MAX_VALUE];

Arrays.chop(T[] a, int newlength);

Box<int>[] ... = new Box<int>[];

char[] frozen = new char[20L].freeze();

Arrays 2.0int[] values = new int[Long.MAX_VALUE];

Arrays.chop(T[] a, int newlength);

Box<int>[] ... = new Box<int>[];

char[] frozen = new char[20L].freeze();

Point[] points = new Point[3]; Stack

var X

var Y

var X

var Y

var X

var Y

points[0]

points[1]

points[2]

Cleaner API

Who knows the Cleaner API?

You should - it’s around since Java 1.4 ;-)

Cleaner APIpackage java.nio;

import sun.misc.Cleaner;

class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer {

private static class Deallocator implements Runnable { private Deallocator(long address, long size, int capacity) {...}

public void run() {...} }

private final Cleaner cleaner; DirectByteBuffer(int cap) { ... cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); } }

Cleaner API

public selfCleaning() { try(AutoCleaning autoCleaning : new AutoCleaning()) { // do your thing here } }

Cleaner APIpublic class AutoCleaning implements AutoCloseable { // A cleaner, preferably one shared within a library private static final Cleaner cleaner = ...;

static class State implements Runnable {

State(...) {/* initialize State needed for cleaning action */} public void run() {/*cleanup action accessing State, executed at most once*/} }

private final State state; private final Cleaner.Cleanable cleanable;

public AutoCleaning() { this.state = new State(...); this.cleanable = cleaner.register(this, state); }

public void close() { cleanable.clean(); }}

More excitingstuff upcoming…

Class Dynamic

Class Dynamic

•Templating functionality

Class Dynamic

•Templating functionality•Aspect-like approach

Class Dynamic

•Templating functionality•Aspect-like approach•Group common functionality

Class Dynamic

•Templating functionality•Aspect-like approach•Group common functionality•Enhanced Proxies

Class Dynamic

•Templating functionality•Aspect-like approach•Group common functionality•Enhanced Proxies

R methodName(ARGS) { synchronized (this) { underlying.methodName(ARGS); }}

Collections::sychronizedMap

Class Dynamic

•Templating functionality•Aspect-like approach•Group common functionality•Enhanced Proxies

Logging / Tracing

R methodName(ARGS) { logger.trace("Before methodname X"); underlying.methodName(ARGS); logger.trace("After methodname X");}

Class Dynamic

•Templating functionality•Aspect-like approach•Group common functionality•Enhanced Proxies

Your Use Case!

SpinWait Hints

SpinWait Hints

Hints the JVM that a busy spin’s upcoming

SpinWait Hints

Hints the JVM that a busy spin’s upcoming

JVM CAN intrinsify to use a WAIT opcode for the specific platform / CPU

SpinWait Hints

Hints the JVM that a busy spin’s upcoming

JVM CAN intrinsify to use a WAIT opcode for the specific platform / CPU

No-Op implementation for non supported CPUs

SpinWait Hints

Hints the JVM that a busy spin’s upcoming

JVM CAN intrinsify to use a WAIT opcode for the specific platform / CPU

No-Op implementation for non supported CPUs

while (!shutdown) { while (queue.length == 0) { // Hint the JVM to intrinsify wait // opcode otherwise busy spin Thread.onSpinWait(); } consume(queue);}

What Else?

No idea!

A lot is changing now.Java / JVM will be different.

What Else?

No idea!

A lot is changing now.Java / JVM will be different.

Don’t forget about Jigsaw,test your application with Java 9 EA builds!

https://jdk9.java.net/jigsaw/

Questions?github.com/noctarius

@noctarius2k

More information:• http://openjdk.java.net/jeps/193 • http://openjdk.java.net/jeps/254 • http://openjdk.java.net/jeps/285 • http://openjdk.java.net/projects/valhalla/ • http://cr.openjdk.java.net/~jrose/arrays/frozen-array-value-rules.html • https://twitter.com/PaulSandoz/status/623891528432394240 • http://openjdk.java.net/projects/panama/ • http://cr.openjdk.java.net/~jrose/values/values-0.html • http://cr.openjdk.java.net/~briangoetz/valhalla/spec-classdyn.html • http://blog.codefx.org/java/dev/the-road-to-valhalla/

http://openjdk.java.net/jeps/259 http://openjdk.java.net/jeps/286 http://openjdk.java.net/jeps/276 http://openjdk.java.net/jeps/269 http://openjdk.java.net/jeps/266 http://openjdk.java.net/jeps/191 http://openjdk.java.net/jeps/186 http://openjdk.java.net/jeps/277