Unsafe: to be or to be removed?
-
Upload
alexey-fyodorov -
Category
Engineering
-
view
1.269 -
download
2
Transcript of Unsafe: to be or to be removed?
UnsafeandJava9/10АлексейФедоров,
Одноклассники/ JUG.ru@23derevo
2 @23derevo
Что такое Unsafe
• Оченьспециальныйобъект• СуществуетсJDK1.4 — уже15лет• НуженвClassLibrary,чтобыоттудадергать JVM
3 @23derevo
Что такое Unsafe
• Оченьспециальныйобъект• СуществуетсJDK1.4 — уже15лет• НуженвClassLibrary,чтобыоттудадергать JVM
“AVM/libraryinterface,designedstrictlyforusewithintheJDK”
MarkReinhold,JavaPlatformArchitectJVMLS2015
4 @23derevo
Используется в разных частях JDK
• 1.4— Reflection,Serialization,NIO• 1.5— JSR166(atomics,locks),CORBA,AWT• 6.0— JSR166(CopyOnWriteArrayList etc.)• 7 — JSR166(ForkJoin etc.),BigDecimal, j.l.invoke• 8— JSR166(много!),MacOSXobjectiveCbridge
5 @23derevo
sun.misc.Unsafe
• Лежитвприватномпакетеsun.misc- раньшевSunJDK- потомвOpenJDK- перекочевалвOracleJDK
6 @23derevo
А что на других JDK?
7 @23derevo
А что на других JDK?
public final class Unsafe {
static {…Reflection.registerMethodsToFilter(
Unsafe.class, "getUnsafe");…
}
private Unsafe() {}
private static final Unsafe theUnsafe = new Unsafe();
@CallerSensitivepublic static Unsafe getUnsafe() {
Class cc = Reflection.getCallerClass();if (cc.getClassLoader() != null)
throw new SecurityException("Unsafe");return theUnsafe;
}
Как получить Unsafepublic static final Unsafe UNSAFE = getUnsafe();
private static Unsafe getUnsafe() {try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);return (Unsafe) f.get(null);
} catch (Exception e) {throw new RuntimeException(e);
}}
10 @23derevo
И всё???
ПоумолчаниюSecutiry ManagerвJavaвыключен!
11 @23derevo
И всё???
$ java -Djava.security.manager
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.sun.misc")
ПоумолчаниюSecutiry ManagerвJavaвыключен!
«Тебя предупреждали»
$ javac Test.java
Test.java:2: warning: Unsafe is internal proprietary API and may be removed in a future releaseimport sun.misc.Unsafe;
^
«Да мне пофиг!»
$ javac Test.java
Test.java:2: warning: Unsafe is internal proprietary API and may be removed in a future releaseimport sun.misc.Unsafe;
^
$ javac -XDignore.symbol.file Test.java
ЧтоумеетUnsafe?
Demo1.AtomicInteger
package java.day.kiev;
public class MyUnsafe {public native int getInt(long address);
#include <jni.h>JNIEXPORT jint JNICALLJava_snow_misc_MyUnsafe(JNIEnv* env,
jobject myUnsafe, jlong address) {return *(jint*)address;
}
Create stack frameMove arguments according to ABI
Wrap objects into JNI handlesObtain JNIEnv* and jclass
Trace method_entryLock if synchronized
Lazy lookup and linkingin_java à in_native thread transition
Call the native functionCheck for safepoint
Switch state to in_javaUnlock if synchronized
Notify method_exitUnwrap result, reset JNI handles block
Handle exceptionsRemove stack frame
Сколько стоит JNI
Create stack frameMove arguments according to ABI
Wrap objects into JNI handlesObtain JNIEnv* and jclass
Trace method_entryLock if synchronized
Lazy lookup and linkingin_java à in_native thread transition
Call the native functionCheck for safepoint
Switch state to in_javaUnlock if synchronized
Notify method_exitUnwrap result, reset JNI handles block
Handle exceptionsRemove stack frame
Сколько стоит JNI
8+8
20 @23derevo
Intrinsics
• Большинствометодов— intrisics:- getInt —> mov- compareAndSwapInt —> cmpxchg
CASpublic final native boolean compareAndSwapInt(
Object o, long offset, int expected, int x);
public final int getAndAddInt(Object o, long offset, int delta) {
int v;do {
v = getIntVolatile(o, offset);} while (!compareAndSwapInt(
o, offset, v, v + delta));return v;
}
AtomicInteger — i.getAndAdd(5)
loop:mov 0xc(%r10),%eaxmov %eax,%r11dadd $0x5,%r11dlock cmpxchg %r11d,0xc(%r10)sete %r11bmovzbl %r11b,%r11dtest %r11d,%r11dje loop
JDK 7u72-XX:+PrintAssembly
AtomicInteger — i.getAndAdd(5)
loop:mov 0xc(%r10),%eaxmov %eax,%r11dadd $0x5,%r11dlock cmpxchg %r11d,0xc(%r10)sete %r11bmovzbl %r11b,%r11dtest %r11d,%r11dje loop
JDK 7u72 JDK 8u66
lock addl $0x5,0xc(%r10)
-XX:+PrintAssembly
AtomicInteger — i.getAndAdd(5)
loop:mov 0xc(%r10),%eaxmov %eax,%r11dadd $0x5,%r11dlock cmpxchg %r11d,0xc(%r10)sete %r11bmovzbl %r11b,%r11dtest %r11d,%r11dje loop
JDK 7u72 JDK 8u66
lock addl $0x5,0xc(%r10)
83
4615 11
132105
45 43
1 2 3 4
ops/μ
s
threads
-XX:+PrintAssembly
HowtofreememoryusingJavaUnsafe?
http://stackoverflow.com/questions/24429777
Demo2.freeMemory
27 @23derevo
hashCode (thanks to @AndreiPangin)
-XX:hashCode=n(http://habr.ru/post/165683/)• 0– Park-MillerRNG (поумолчанию)• 1– f(адрес,глобальное_состояние)• 2– константа1• 3– последовательныйсчетчик• 4– адресобъекта• 5– Thread-local Xorshift
Usecases
29 @23derevo
Off-heap Collections
• Lists,sets,maps- Largecapacity>2GB- PredictableGCpauses- Noheapfragmentation- Datalocality
Data locality
Key
ValueKey Value
Map.Entry Off-heaplayout
a b c a b c a b c
31 @23derevo
I/O and persistence
• Persistentcachesandstorages-Memory-mappedfiles(64-bit)- Sharedmemory
• CooperationwithOS- Pointerarithmetic,alignment- mlock,madvise etc.
32 @23derevo
IPC, Messaging
• Concurrentoff-heapbuffersandqueues• High-performancemessaging- Disruptor- Aeron:6Mmsg/s
• Shareddatastructures- ChronicleMap
УдалениеUnsafe
34 @23derevo
Тактика действий в случае удаления Unsafe
35 @23derevo
Тактика действий в случае удаления Unsafe
36 @23derevo
• Переписатькускикода- JNI- Reflection- NIO- etc.
Тактика действий в случае удаления Unsafe
37 @23derevo
• Переписатькускикода- JNI- Reflection- NIO- Etc.
• Какдействовать1. Новыйlayer:wrapper надUnsafe2. ЗаменитьнаwrapperнадpublicAPI
Тактика действий в случае удаления Unsafe
Беда1:PerformanceDegradation
Cassandra
Netty
Guava
Hazelcast
Mockito
GWT
HadoopZookeeper Kafka
Gson
Neo4j
Grails
Spring
Disruptor
JRuby
Scala
Akka
Unsafe
Cassandra
Netty
Guava
Hazelcast
Mockito
GWT
HadoopZookeeper Kafka
Gson
Neo4j
Grails
Spring
Disruptor
JRuby
Scala
Akka
Беда2:Транзитивныйlock-in
42 @23derevo
Как так получилось?
$ javac Test.java
Test.java:2: warning: Unsafe is internal proprietary API and may be removed in a future releaseimport sun.misc.Unsafe;
^
Слишкоммало евангелизма,Oracle!
Какразвиваласьситуация
45 @23derevo
Хронология событий
• JEP200:TheModularJDK- MarkReinholdвыступилна Devoxx 2014
• Постна blog.dripstat.com• ChrisEngelbert изHazelcast началдискуссию
46 @23derevo
Хронология событий
• JEP200:TheModularJDK- MarkReinholdвыступилна Devoxx 2014
• Постна blog.dripstat.com• ChrisEngelbert изHazelcast началдискуссию• ОбсуждениенаJCrete
47 @23derevo
Хронология событий
• JEP200:TheModularJDK- MarkReinholdвыступилна Devoxx 2014
• Постна blog.dripstat.com• ChrisEngelbert изHazelcast началдискуссию• ОбсуждениенаJCrete• MarkReinholdвыступилнаJVMLS• JEP260:EncapsulateMostInternalAPIs• JavaOne 2015— 5разъясняющихпрезентаций
48 @23derevo
План замены Unsafe на public API
• ReplacementinJDK8à hideinJDK9- sun.misc.BASE64Encoderetc.- Availableviacommand-lineflag
49 @23derevo
План замены Unsafe на public API
• ReplacementinJDK8à hideinJDK9- sun.misc.BASE64Encoderetc.- Availableviacommand-lineflag
• NoreplacementinJDK8à availableoutside- sun.misc.Unsafe,sun.reflect.ReflectionFactory- sun.misc.Cleaner,sun.misc.SignalHandler
50 @23derevo
План замены Unsafe на public API
• ReplacementinJDK8à hideinJDK9- sun.misc.BASE64Encoderetc.- Availableviacommand-lineflag
• NoreplacementinJDK8à availableoutside- sun.misc.Unsafe,sun.reflect.ReflectionFactory- sun.misc.Cleaner,sun.misc.SignalHandler
• ReplacementinJDK9à hideinJDK9,removeinJDK10
Чтоприходитназамену
JEP 193: VarHandles (Expected in Java 9)
class Queue {int size;...
}
VarHandle queueSize= VarHandles.lookup().findFieldHandle(
Queue.class, "size", int.class);
queueSize.addAndGet(10);
53
• get, getVolatile, getAcquire, getOpaque• set, setVolatile, setRelease, setOpaque• compareAndSet, compareAndExchangeVolatile• compareAndExchangeAcquire, compareAndExchangeRelease• weakCompareAndSet, weakCompareAndSetAcquire, weakCompareAndSetRelease
• getAndSet, getAndAdd, addAndGet
VarHandle handle = VarHandles.arrayElement(int[].class)
VarHandle viewH = VarHandles.arrayElementViewHandle(byte[].class, long[].class, true);
54 @23derevo
Итоги
• Oracleуслышалсообществоиизменилпланы- Oracleготовидальшеслушать- Сообществопредставляетсобойсилу,занимэкосистема
• Unsafeвсе-такивыпилят- Нопостепенно,втечениенесколькихлет
55 @23derevo
Полезные материалы
• MarkReinhold@JVMLS2015- https://youtu.be/4HG0YQVy8UM
• PaulSandoz@JavaOne 2015- http://cr.openjdk.java.net/~psandoz/conferences/2015-JavaOne/j1-2015-unsafe-CON7076.pdf
• AndreiPangin @Joker2015- http://www.slideshare.net/AndreiPangin/do-we-need-unsafe-in-java
56 @23derevo
Development @ Одноклассники
• TechBlog- http://habrahabr.ru/company/odnoklassniki
• Opensource- https://github.com/odnoklassniki
• Career- http://v.ok.ru
БлагодарюАндреяПаньгина
@AndreiPangin
Вопросыиответы
Спасибозавнимание!