--- title: Java éæ³ç±» Unsafe 详解 category: Java tag: - Javaåºç¡ --- > æ¬ææ´çå®åèªä¸é¢è¿ä¸¤ç¯ä¼ç§çæç« ï¼ > > - [Java éæ³ç±»ï¼Unsafe åºç¨è§£æ - ç¾å¢ææ¯å¢é -2019](https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html) > - [Java åååä¹ Unsafe 类详解 - ç ååä¸ - 2021](https://xie.infoq.cn/article/8b6ed4195e475bfb32dacc5cb) é è¯»è¿ JUC æºç çåå¦ï¼ä¸å®ä¼åç°å¾å¤å¹¶åå·¥å ·ç±»é½è°ç¨äºä¸ä¸ªå«å `Unsafe` çç±»ã é£è¿ä¸ªç±»ä¸»è¦æ¯ç¨æ¥å¹²ä»ä¹çå¢ï¼æä»ä¹ä½¿ç¨åºæ¯å¢ï¼è¿ç¯æç« å°±å¸¦ä½ ææ¸ æ¥ï¼ ## Unsafe ä»ç» `Unsafe` æ¯ä½äº `sun.misc` å ä¸çä¸ä¸ªç±»ï¼ä¸»è¦æä¾ä¸äºç¨äºæ§è¡ä½çº§å«ãä¸å®å ¨æä½çæ¹æ³ï¼å¦ç´æ¥è®¿é®ç³»ç»å åèµæºãèªä¸»ç®¡çå åèµæºçï¼è¿äºæ¹æ³å¨æå Java è¿è¡æçãå¢å¼º Java è¯è¨åºå±èµæºæä½è½åæ¹é¢èµ·å°äºå¾å¤§çä½ç¨ãä½ç±äº `Unsafe` 类使 Java è¯è¨æ¥æäºç±»ä¼¼ C è¯è¨æé䏿 ·æä½å å空é´çè½åï¼è¿æ çä¹å¢å äºç¨åºåçç¸å ³æéé®é¢çé£é©ãå¨ç¨åºä¸è¿åº¦ã䏿£ç¡®ä½¿ç¨ `Unsafe` ç±»ä¼ä½¿å¾ç¨åºåºéçæ¦çå大ï¼ä½¿å¾ Java è¿ç§å®å ¨çè¯è¨åå¾ä¸åâå®å ¨âï¼å æ¤å¯¹ `Unsafe` ç使ç¨ä¸å®è¦æ éã å¦å¤ï¼`Unsafe` æä¾çè¿äºåè½çå®ç°éè¦ä¾èµæ¬å°æ¹æ³ï¼Native Methodï¼ãä½ å¯ä»¥å°æ¬å°æ¹æ³ç使¯ Java ä¸ä½¿ç¨å ¶ä»ç¼ç¨è¯è¨ç¼åçæ¹æ³ãæ¬å°æ¹æ³ä½¿ç¨ **`native`** å ³é®å修饰ï¼Java 代ç ä¸åªæ¯å£°ææ¹æ³å¤´ï¼å ·ä½çå®ç°åäº¤ç» **æ¬å°ä»£ç **ã  **为ä»ä¹è¦ä½¿ç¨æ¬å°æ¹æ³å¢ï¼** 1. éè¦ç¨å° Java ä¸ä¸å ·å¤çä¾èµäºæä½ç³»ç»çç¹æ§ï¼Java å¨å®ç°è·¨å¹³å°çåæ¶è¦å®ç°å¯¹åºå±çæ§å¶ï¼éè¦åå©å ¶ä»è¯è¨åæ¥ä½ç¨ã 2. 对äºå ¶ä»è¯è¨å·²ç»å®æçä¸äºç°æåè½ï¼å¯ä»¥ä½¿ç¨ Java ç´æ¥è°ç¨ã 3. ç¨åºå¯¹æ¶é´æææå¯¹æ§è½è¦æ±é叏髿¶ï¼æå¿ è¦ä½¿ç¨æ´å åºå±çè¯è¨ï¼ä¾å¦ C/C++çè³æ¯æ±ç¼ã å¨ JUC å çå¾å¤å¹¶åå·¥å ·ç±»å¨å®ç°å¹¶åæºå¶æ¶ï¼é½è°ç¨äºæ¬å°æ¹æ³ï¼éè¿å®ä»¬æç ´äº Java è¿è¡æ¶ççéï¼è½å¤æ¥è§¦å°æä½ç³»ç»åºå±çæäºåè½ã对äºå䏿¬å°æ¹æ³ï¼ä¸åçæä½ç³»ç»å¯è½ä¼éè¿ä¸åçæ¹å¼æ¥å®ç°ï¼ä½æ¯å¯¹äºä½¿ç¨è æ¥è¯´æ¯éæçï¼æç»é½ä¼å¾å°ç¸åçç»æã ## Unsafe å建 `sun.misc.Unsafe` é¨åæºç å¦ä¸ï¼ ```java public final class Unsafe { // åä¾å¯¹è±¡ private static final Unsafe theUnsafe; ...... private Unsafe() { } @CallerSensitive public static Unsafe getUnsafe() { Class var0 = Reflection.getCallerClass(); // ä» å¨å¼å¯¼ç±»å è½½å¨`BootstrapClassLoader`å è½½æ¶æåæ³ if(!VM.isSystemDomainLoader(var0.getClassLoader())) { throw new SecurityException("Unsafe"); } else { return theUnsafe; } } } ``` `Unsafe` 类为ä¸åä¾å®ç°ï¼æä¾éææ¹æ³ `getUnsafe` è·å `Unsafe`å®ä¾ãè¿ä¸ªçä¸å»è²ä¼¼å¯ä»¥ç¨æ¥è·å `Unsafe` å®ä¾ã使¯ï¼å½æä»¬ç´æ¥è°ç¨è¿ä¸ªéææ¹æ³çæ¶åï¼ä¼æåº `SecurityException` å¼å¸¸ï¼ ```bash Exception in thread "main" java.lang.SecurityException: Unsafe at sun.misc.Unsafe.getUnsafe(Unsafe.java:90) at com.cn.test.GetUnsafeTest.main(GetUnsafeTest.java:12) ``` **为ä»ä¹ `public static` æ¹æ³æ æ³è¢«ç´æ¥è°ç¨å¢ï¼** è¿æ¯å 为å¨`getUnsafe`æ¹æ³ä¸ï¼ä¼å¯¹è°ç¨è ç`classLoader`è¿è¡æ£æ¥ï¼å¤æå½åç±»æ¯å¦ç±`Bootstrap classLoader`å è½½ï¼å¦æä¸æ¯çè¯é£ä¹å°±ä¼æåºä¸ä¸ª`SecurityException`å¼å¸¸ãä¹å°±æ¯è¯´ï¼åªæå¯å¨ç±»å è½½å¨å è½½çç±»æè½å¤è°ç¨ Unsafe ç±»ä¸çæ¹æ³ï¼æ¥é²æ¢è¿äºæ¹æ³å¨ä¸å¯ä¿¡ç代ç ä¸è¢«è°ç¨ã **为ä»ä¹è¦å¯¹ Unsafe ç±»è¿è¡è¿ä¹è°¨æ ç使ç¨éå¶å¢?** `Unsafe` æä¾çåè½è¿äºåºå±ï¼å¦ç´æ¥è®¿é®ç³»ç»å åèµæºãèªä¸»ç®¡çå åèµæºçï¼ï¼å®å ¨éæ£ä¹æ¯è¾å¤§ï¼ä½¿ç¨ä¸å½çè¯ï¼å¾å®¹æåºç°å¾ä¸¥éçé®é¢ã **å¦è¥æ³ä½¿ç¨ `Unsafe` è¿ä¸ªç±»çè¯ï¼åºè¯¥å¦ä½è·åå ¶å®ä¾å¢ï¼** è¿éä»ç»ä¸¤ä¸ªå¯è¡çæ¹æ¡ã 1ãå©ç¨åå°è·å¾ Unsafe ç±»ä¸å·²ç»å®ä¾å宿çåä¾å¯¹è±¡ `theUnsafe` ã ```java private static Unsafe reflectGetUnsafe() { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); return (Unsafe) field.get(null); } catch (Exception e) { log.error(e.getMessage(), e); return null; } } ``` 2ãä»`getUnsafe`æ¹æ³ç使ç¨éå¶æ¡ä»¶åºåï¼éè¿ Java å½ä»¤è¡å½ä»¤`-Xbootclasspath/a`æè°ç¨ Unsafe ç¸å ³æ¹æ³çç±» A æå¨ jar å è·¯å¾è¿½å å°é»è®¤ç bootstrap è·¯å¾ä¸ï¼ä½¿å¾ A 被å¼å¯¼ç±»å è½½å¨å è½½ï¼ä»èéè¿`Unsafe.getUnsafe`æ¹æ³å®å ¨çè·å Unsafe å®ä¾ã ```bash java -Xbootclasspath/a: ${path} // å ¶ä¸path为è°ç¨Unsafeç¸å ³æ¹æ³çç±»æå¨jarå è·¯å¾ ``` ## Unsafe åè½ æ¦æ¬çæ¥è¯´ï¼`Unsafe` ç±»å®ç°åè½å¯ä»¥è¢«å为ä¸é¢ 8 ç±»ï¼ 1. å åæä½ 2. å åå±é 3. 对象æä½ 4. æ°æ®æä½ 5. CAS æä½ 6. 线ç¨è°åº¦ 7. Class æä½ 8. ç³»ç»ä¿¡æ¯ ### å åæä½ #### ä»ç» å¦æä½ æ¯ä¸ä¸ªåè¿ C æè C++ çç¨åºåï¼ä¸å®å¯¹å åæä½ä¸ä¼éçï¼èå¨ Java 䏿¯ä¸å è®¸ç´æ¥å¯¹å åè¿è¡æä½çï¼å¯¹è±¡å åçåé å忶齿¯ç± JVM èªå·±å®ç°çã使¯å¨ `Unsafe` ä¸ï¼æä¾çä¸åæ¥å£å¯ä»¥ç´æ¥è¿è¡å åæä½ï¼ ```java //åé æ°çæ¬å°ç©ºé´ public native long allocateMemory(long bytes); //éæ°è°æ´å å空é´çå¤§å° public native long reallocateMemory(long address, long bytes); //å°å å设置为æå®å¼ public native void setMemory(Object o, long offset, long bytes, byte value); //å åæ·è´ public native void copyMemory(Object srcBase, long srcOffset,Object destBase, long destOffset,long bytes); //æ¸ é¤å å public native void freeMemory(long address); ``` 使ç¨ä¸é¢ç代ç è¿è¡æµè¯ï¼ ```java private void memoryTest() { int size = 4; long addr = unsafe.allocateMemory(size); long addr3 = unsafe.reallocateMemory(addr, size * 2); System.out.println("addr: "+addr); System.out.println("addr3: "+addr3); try { unsafe.setMemory(null,addr ,size,(byte)1); for (int i = 0; i < 2; i++) { unsafe.copyMemory(null,addr,null,addr3+size*i,4); } System.out.println(unsafe.getInt(addr)); System.out.println(unsafe.getLong(addr3)); }finally { unsafe.freeMemory(addr); unsafe.freeMemory(addr3); } } ``` å çç»æè¾åºï¼ ``` addr: 2433733895744 addr3: 2433733894944 16843009 72340172838076673 ``` åæä¸ä¸è¿è¡ç»æï¼é¦å 使ç¨`allocateMemory`æ¹æ³ç³è¯· 4 åèé¿åº¦çå å空é´ï¼è°ç¨`setMemory`æ¹æ³åæ¯ä¸ªåèåå ¥å 容为`byte`ç±»åç 1ï¼å½ä½¿ç¨ Unsafe è°ç¨`getInt`æ¹æ³æ¶ï¼å 为ä¸ä¸ª`int`ååéå 4 个åèï¼ä¼ä¸æ¬¡æ§è¯»å 4 个åèï¼ç»æä¸ä¸ª`int`çå¼ï¼å¯¹åºçåè¿å¶ç»æä¸º 16843009ã ä½ å¯ä»¥éè¿ä¸å¾çè§£è¿ä¸ªè¿ç¨ï¼  å¨ä»£ç ä¸è°ç¨`reallocateMemory`æ¹æ³éæ°åé äºä¸å 8 åèé¿åº¦çå å空é´ï¼éè¿æ¯è¾`addr`å`addr3`å¯ä»¥çå°åä¹åç³è¯·çå åå°åæ¯ä¸åçãå¨ä»£ç ä¸ç第äºä¸ª for 循ç¯éï¼è°ç¨`copyMemory`æ¹æ³è¿è¡äºä¸¤æ¬¡å åçæ·è´ï¼æ¯æ¬¡æ·è´å åå°å`addr`å¼å§ç 4 个åèï¼å嫿·è´å°ä»¥`addr3`å`addr3+4`å¼å§çå å空é´ä¸ï¼  æ·è´å®æåï¼ä½¿ç¨`getLong`æ¹æ³ä¸æ¬¡æ§è¯»å 8 个åèï¼å¾å°`long`ç±»åçå¼ä¸º 72340172838076673ã éè¦æ³¨æï¼éè¿è¿ç§æ¹å¼åé çå åå±äº å å¤å å ï¼æ¯æ æ³è¿è¡åå¾åæ¶çï¼éè¦æä»¬æè¿äºå åå½åä¸ç§èµæºå»æå¨è°ç¨`freeMemory`æ¹æ³è¿è¡éæ¾ï¼å¦åä¼äº§çå åæ³æ¼ãéç¨çæä½å 忹弿¯å¨`try`䏿§è¡å¯¹å åçæä½ï¼æç»å¨`finally`åä¸è¿è¡å åçéæ¾ã **为ä»ä¹è¦ä½¿ç¨å å¤å åï¼** - 对åå¾åæ¶åé¡¿çæ¹åãç±äºå å¤å åæ¯ç´æ¥åæä½ç³»ç»ç®¡çè䏿¯ JVMï¼æä»¥å½æä»¬ä½¿ç¨å å¤å åæ¶ï¼å³å¯ä¿æè¾å°çå å å åè§æ¨¡ãä»èå¨ GC æ¶åå°åæ¶å顿对äºåºç¨çå½±åã - æåç¨åº I/O æä½çæ§è½ãéå¸¸å¨ I/O éä¿¡è¿ç¨ä¸ï¼ä¼åå¨å å å åå°å å¤å åçæ°æ®æ·è´æä½ï¼å¯¹äºéè¦é¢ç¹è¿è¡å åé´æ°æ®æ·è´ä¸çå½å¨æè¾ççæåæ°æ®ï¼é½å»ºè®®åå¨å°å å¤å åã #### å ¸ååºç¨ `DirectByteBuffer` æ¯ Java ç¨äºå®ç°å å¤å åçä¸ä¸ªéè¦ç±»ï¼é常ç¨å¨éä¿¡è¿ç¨ä¸åç¼å²æ± ï¼å¦å¨ NettyãMINA ç NIO æ¡æ¶ä¸åºç¨å¹¿æ³ã`DirectByteBuffer` 对äºå å¤å åçå建ã使ç¨ã鿝çé»è¾åç± Unsafe æä¾çå å¤å å API æ¥å®ç°ã ä¸å¾ä¸º `DirectByteBuffer` æé 彿°ï¼å建 `DirectByteBuffer` çæ¶åï¼éè¿ `Unsafe.allocateMemory` åé å åã`Unsafe.setMemory` è¿è¡å ååå§åï¼èåæå»º `Cleaner` 对象ç¨äºè·è¸ª `DirectByteBuffer` 对象çåå¾åæ¶ï¼ä»¥å®ç°å½ `DirectByteBuffer` 被åå¾åæ¶æ¶ï¼åé çå å¤å åä¸èµ·è¢«éæ¾ã ```java DirectByteBuffer(int cap) { // package-private super(-1, 0, cap, cap); boolean pa = VM.isDirectMemoryPageAligned(); int ps = Bits.pageSize(); long size = Math.max(1L, (long)cap + (pa ? ps : 0)); Bits.reserveMemory(size, cap); long base = 0; try { // åé å åå¹¶è¿ååºå°å base = unsafe.allocateMemory(size); } catch (OutOfMemoryError x) { Bits.unreserveMemory(size, cap); throw x; } // å ååå§å unsafe.setMemory(base, size, (byte) 0); if (pa && (base % ps != 0)) { // Round up to page boundary address = base + ps - (base & (ps - 1)); } else { address = base; } // è·è¸ª DirectByteBuffer 对象çåå¾åæ¶ï¼ä»¥å®ç°å å¤å åéæ¾ cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); att = null; } ``` ### å åå±é #### ä»ç» å¨ä»ç»å åå±éåï¼éè¦ç¥éç¼è¯å¨å CPU ä¼å¨ä¿è¯ç¨åºè¾åºç»æä¸è´çæ åµä¸ï¼ä¼å¯¹ä»£ç è¿è¡éæåºï¼ä»æä»¤ä¼åè§åº¦æåæ§è½ãèæä»¤éæåºå¯è½ä¼å¸¦æ¥ä¸ä¸ªä¸å¥½çç»æï¼å¯¼è´ CPU çé«éç¼ååå å䏿°æ®çä¸ä¸è´ï¼èå åå±éï¼`Memory Barrier`ï¼å°±æ¯éè¿é»æ¢å±é两边çæä»¤éæåºä»èé¿å ç¼è¯å¨å硬件ç䏿£ç¡®ä¼åæ åµã å¨ç¡¬ä»¶å±é¢ä¸ï¼å åå±éæ¯ CPU 为äºé²æ¢ä»£ç è¿è¡éæåºèæä¾çæä»¤ï¼ä¸åç硬件平å°ä¸å®ç°å åå±éçæ¹æ³å¯è½å¹¶ä¸ç¸åãå¨ Java8 ä¸ï¼å¼å ¥äº 3 个å åå±éç彿°ï¼å®å±è½äºæä½ç³»ç»åºå±çå·®å¼ï¼å 许å¨ä»£ç ä¸å®ä¹ãå¹¶ç»ä¸ç± JVM æ¥çæå åå±éæä»¤ï¼æ¥å®ç°å åå±éçåè½ã `Unsafe` 䏿ä¾äºä¸é¢ä¸ä¸ªå åå±éç¸å ³æ¹æ³ï¼ ```java //å åå±éï¼ç¦æ¢loadæä½éæåºãå±éåçloadæä½ä¸è½è¢«éæåºå°å±éåï¼å±éåçloadæä½ä¸è½è¢«éæåºå°å±éå public native void loadFence(); //å åå±éï¼ç¦æ¢storeæä½éæåºãå±éåçstoreæä½ä¸è½è¢«éæåºå°å±éåï¼å±éåçstoreæä½ä¸è½è¢«éæåºå°å±éå public native void storeFence(); //å åå±éï¼ç¦æ¢loadãstoreæä½éæåº public native void fullFence(); ``` å åå±éå¯ä»¥çå对å åéæºè®¿é®çæä½ä¸çä¸ä¸ªåæ¥ç¹ï¼ä½¿å¾æ¤ç¹ä¹åçææè¯»åæä½é½æ§è¡åæå¯ä»¥å¼å§æ§è¡æ¤ç¹ä¹åçæä½ã以`loadFence`æ¹æ³ä¸ºä¾ï¼å®ä¼ç¦æ¢è¯»æä½éæåºï¼ä¿è¯å¨è¿ä¸ªå±éä¹åçææè¯»æä½é½å·²ç»å®æï¼å¹¶ä¸å°ç¼åæ°æ®è®¾ä¸ºæ æï¼éæ°ä»ä¸»åä¸è¿è¡å è½½ã çå°è¿ä¼°è®¡å¾å¤å°ä¼ä¼´ä»¬ä¼æ³å°`volatile`å ³é®åäºï¼å¦æå¨åæ®µä¸æ·»å äº`volatile`å ³é®åï¼å°±è½å¤å®ç°å段å¨å¤çº¿ç¨ä¸çå¯è§æ§ãåºäºè¯»å åå±éï¼æä»¬ä¹è½å®ç°ç¸åçåè½ãä¸é¢å®ä¹ä¸ä¸ªçº¿ç¨æ¹æ³ï¼å¨çº¿ç¨ä¸å»ä¿®æ¹`flag`æ å¿ä½ï¼æ³¨æè¿éç`flag`æ¯æ²¡æè¢«`volatile`修饰çï¼ ```java @Getter class ChangeThread implements Runnable{ /**volatile**/ boolean flag=false; @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("subThread change flag to:" + flag); flag = true; } } ``` å¨ä¸»çº¿ç¨ç`while`循ç¯ä¸ï¼å å ¥å åå±éï¼æµè¯æ¯å¦è½å¤æç¥å°`flag`çä¿®æ¹ååï¼ ```java public static void main(String[] args){ ChangeThread changeThread = new ChangeThread(); new Thread(changeThread).start(); while (true) { boolean flag = changeThread.isFlag(); unsafe.loadFence(); //å å ¥è¯»å åå±é if (flag){ System.out.println("detected flag changed"); break; } } System.out.println("main thread end"); } ``` è¿è¡ç»æï¼ ``` subThread change flag to:false detected flag changed main thread end ``` èå¦æå æä¸é¢ä»£ç ä¸ç`loadFence`æ¹æ³ï¼é£ä¹ä¸»çº¿ç¨å°æ æ³æç¥å°`flag`åççååï¼ä¼ä¸ç´å¨`while`ä¸å¾ªç¯ãå¯ä»¥ç¨å¾æ¥è¡¨ç¤ºä¸é¢çè¿ç¨ï¼  äºè§£ Java å 忍¡åï¼`JMM`ï¼çå°ä¼ä¼´ä»¬åºè¯¥æ¸ æ¥ï¼è¿è¡ä¸ç线ç¨ä¸æ¯ç´æ¥è¯»å主å åä¸çåéçï¼åªè½æä½èªå·±å·¥ä½å åä¸çåéï¼ç¶å忥å°ä¸»å åä¸ï¼å¹¶ä¸çº¿ç¨çå·¥ä½å 忝ä¸è½å ±äº«çãä¸é¢çå¾ä¸çæµç¨å°±æ¯å线ç¨åå©äºä¸»å åï¼å°ä¿®æ¹åçç»æåæ¥ç»äºä¸»çº¿ç¨ï¼è¿èä¿®æ¹ä¸»çº¿ç¨ä¸çå·¥ä½ç©ºé´ï¼è·³åºå¾ªç¯ã #### å ¸ååºç¨ å¨ Java 8 ä¸å¼å ¥äºä¸ç§éçæ°æºå¶ââ`StampedLock`ï¼å®å¯ä»¥çææ¯è¯»åéçä¸ä¸ªæ¹è¿çæ¬ã`StampedLock` æä¾äºä¸ç§ä¹è§è¯»éçå®ç°ï¼è¿ç§ä¹è§è¯»éç±»ä¼¼äºæ éçæä½ï¼å®å ¨ä¸ä¼é»å¡å线ç¨è·ååéï¼ä»èç¼è§£è¯»å¤åå°æ¶å线ç¨â饥饿âç°è±¡ãç±äº `StampedLock` æä¾çä¹è§è¯»éä¸é»å¡å线ç¨è·å读éï¼å½çº¿ç¨å ±äº«åéä»ä¸»å å load å°çº¿ç¨å·¥ä½å åæ¶ï¼ä¼å卿°æ®ä¸ä¸è´é®é¢ã 为äºè§£å³è¿ä¸ªé®é¢ï¼`StampedLock` ç `validate` æ¹æ³ä¼éè¿ `Unsafe` ç `loadFence` æ¹æ³å å ¥ä¸ä¸ª `load` å åå±éã ```java public boolean validate(long stamp) { U.loadFence(); return (stamp & SBITS) == (state & SBITS); } ``` ### 对象æä½ #### ä»ç» **ä¾å** ```java import sun.misc.Unsafe; import java.lang.reflect.Field; public class Main { private int value; public static void main(String[] args) throws Exception{ Unsafe unsafe = reflectGetUnsafe(); assert unsafe != null; long offset = unsafe.objectFieldOffset(Main.class.getDeclaredField("value")); Main main = new Main(); System.out.println("value before putInt: " + main.value); unsafe.putInt(main, offset, 42); System.out.println("value after putInt: " + main.value); System.out.println("value after putInt: " + unsafe.getInt(main, offset)); } private static Unsafe reflectGetUnsafe() { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); return (Unsafe) field.get(null); } catch (Exception e) { e.printStackTrace(); return null; } } } ``` è¾åºç»æï¼ ``` value before putInt: 0 value after putInt: 42 value after putInt: 42 ``` **å¯¹è±¡å±æ§** 对象æå屿§çå ååç§»éè·åï¼ä»¥ååæ®µå±æ§å¼çä¿®æ¹ï¼å¨ä¸é¢çä¾åä¸æä»¬å·²ç»æµè¯è¿äºãé¤äºåé¢ç`putInt`ã`getInt`æ¹æ³å¤ï¼Unsafe æä¾äºå ¨é¨ 8 ç§åºç¡æ°æ®ç±»å以å`Object`ç`put`å`get`æ¹æ³ï¼å¹¶ä¸ææç`put`æ¹æ³é½å¯ä»¥è¶è¿è®¿é®æéï¼ç´æ¥ä¿®æ¹å åä¸çæ°æ®ãé 读 openJDK æºç ä¸ç注éåç°ï¼åºç¡æ°æ®ç±»åå`Object`ç读åç¨æä¸åï¼åºç¡æ°æ®ç±»åæ¯ç´æ¥æä½ç屿§å¼ï¼`value`ï¼ï¼è`Object`çæä½åæ¯åºäºå¼ç¨å¼ï¼`reference value`ï¼ãä¸é¢æ¯`Object`çè¯»åæ¹æ³ï¼ ```java //å¨å¯¹è±¡çæå®åç§»å°åè·åä¸ä¸ªå¯¹è±¡å¼ç¨ public native Object getObject(Object o, long offset); //å¨å¯¹è±¡æå®åç§»å°ååå ¥ä¸ä¸ªå¯¹è±¡å¼ç¨ public native void putObject(Object o, long offset, Object x); ``` é¤äºå¯¹è±¡å±æ§çæ®é读åå¤ï¼`Unsafe` è¿æä¾äº **volatile 读å**å**æåºåå ¥**æ¹æ³ã`volatile`è¯»åæ¹æ³çè¦çèå´ä¸æ®é读åç¸åï¼å å«äºå ¨é¨åºç¡æ°æ®ç±»åå`Object`ç±»åï¼ä»¥`int`ç±»å为ä¾ï¼ ```java //å¨å¯¹è±¡çæå®åç§»å°åå¤è¯»åä¸ä¸ªintå¼ï¼æ¯ævolatile loadè¯ä¹ public native int getIntVolatile(Object o, long offset); //å¨å¯¹è±¡æå®åç§»å°åå¤åå ¥ä¸ä¸ªintï¼æ¯ævolatile storeè¯ä¹ public native void putIntVolatile(Object o, long offset, int x); ``` ç¸å¯¹äºæ®éè¯»åæ¥è¯´ï¼`volatile`读åå ·ææ´é«çææ¬ï¼å 为å®éè¦ä¿è¯å¯è§æ§åæåºæ§ã卿§è¡`get`æä½æ¶ï¼ä¼å¼ºå¶ä»ä¸»åä¸è·å屿§å¼ï¼å¨ä½¿ç¨`put`æ¹æ³è®¾ç½®å±æ§å¼æ¶ï¼ä¼å¼ºå¶å°å¼æ´æ°å°ä¸»åä¸ï¼ä»èä¿è¯è¿äºåæ´å¯¹å ¶ä»çº¿ç¨æ¯å¯è§çã æåºåå ¥çæ¹æ³æä»¥ä¸ä¸ä¸ªï¼ ```java public native void putOrderedObject(Object o, long offset, Object x); public native void putOrderedInt(Object o, long offset, int x); public native void putOrderedLong(Object o, long offset, long x); ``` æåºåå ¥çææ¬ç¸å¯¹`volatile`è¾ä½ï¼å 为å®åªä¿è¯åå ¥æ¶çæåºæ§ï¼èä¸ä¿è¯å¯è§æ§ï¼ä¹å°±æ¯ä¸ä¸ªçº¿ç¨åå ¥çå¼ä¸è½ä¿è¯å ¶ä»çº¿ç¨ç«å³å¯è§ã为äºè§£å³è¿éç差弿§ï¼éè¦å¯¹å åå±éçç¥è¯ç¹åè¿ä¸æ¥è¿è¡è¡¥å ï¼é¦å éè¦äºè§£ä¸¤ä¸ªæä»¤çæ¦å¿µï¼ - `Load`ï¼å°ä¸»å åä¸çæ°æ®æ·è´å°å¤çå¨çç¼åä¸ - `Store`ï¼å°å¤çå¨ç¼åçæ°æ®å·æ°å°ä¸»å åä¸ é¡ºåºåå ¥ä¸`volatile`åå ¥çå·®å«å¨äºï¼å¨é¡ºåºåæ¶å å ¥çå åå±éç±»å为`StoreStore`ç±»åï¼èå¨`volatile`åå ¥æ¶å å ¥çå åå±éæ¯`StoreLoad`ç±»åï¼å¦ä¸å¾æç¤ºï¼  卿åºåå ¥æ¹æ³ä¸ï¼ä½¿ç¨çæ¯`StoreStore`å±éï¼è¯¥å±éç¡®ä¿`Store1`ç«å»å·æ°æ°æ®å°å åï¼è¿ä¸æä½å äº`Store2`以ååç»çå卿令æä½ãèå¨`volatile`åå ¥ä¸ï¼ä½¿ç¨çæ¯`StoreLoad`å±éï¼è¯¥å±éç¡®ä¿`Store1`ç«å»å·æ°æ°æ®å°å åï¼è¿ä¸æä½å äº`Load2`ååç»çè£ è½½æä»¤ï¼å¹¶ä¸ï¼`StoreLoad`å±éä¼ä½¿è¯¥å±éä¹åçææå åè®¿é®æä»¤ï¼å æ¬å卿令åè®¿é®æä»¤å ¨é¨å®æä¹åï¼ææ§è¡è¯¥å±éä¹åçå åè®¿é®æä»¤ã ç»¼ä¸æè¿°ï¼å¨ä¸é¢çä¸ç±»åå ¥æ¹æ³ä¸ï¼å¨åå ¥æçæ¹é¢ï¼æç §`put`ã`putOrder`ã`putVolatile`çé¡ºåºæç鿏éä½ã **对象å®ä¾å** ä½¿ç¨ `Unsafe` ç `allocateInstance` æ¹æ³ï¼å 许æä»¬ä½¿ç¨é常è§çæ¹å¼è¿è¡å¯¹è±¡çå®ä¾åï¼é¦å å®ä¹ä¸ä¸ªå®ä½ç±»ï¼å¹¶ä¸å¨æé 彿°ä¸å¯¹å ¶æååéè¿è¡èµå¼æä½ï¼ ```java @Data public class A { private int b; public A(){ this.b =1; } } ``` åå«åºäºæé 彿°ãåå°ä»¥å `Unsafe` æ¹æ³çä¸åæ¹å¼å建对象è¿è¡æ¯è¾ï¼ ```java public void objTest() throws Exception{ A a1=new A(); System.out.println(a1.getB()); A a2 = A.class.newInstance(); System.out.println(a2.getB()); A a3= (A) unsafe.allocateInstance(A.class); System.out.println(a3.getB()); } ``` æå°ç»æåå«ä¸º 1ã1ã0ï¼è¯´æéè¿`allocateInstance`æ¹æ³å建对象è¿ç¨ä¸ï¼ä¸ä¼è°ç¨ç±»çæé æ¹æ³ã使ç¨è¿ç§æ¹å¼å建对象æ¶ï¼åªç¨å°äº`Class`å¯¹è±¡ï¼æä»¥è¯´å¦ææ³è¦è·³è¿å¯¹è±¡çåå§åé¶æ®µæè è·³è¿æé å¨çå®å ¨æ£æ¥ï¼å°±å¯ä»¥ä½¿ç¨è¿ç§æ¹æ³ãå¨ä¸é¢çä¾åä¸ï¼å¦æå° A ç±»çæé 彿°æ¹ä¸º`private`ç±»åï¼å°æ æ³éè¿æé 彿°ååå°å建对象ï¼ä½`allocateInstance`æ¹æ³ä»ç¶ææã #### å ¸ååºç¨ - **常è§å¯¹è±¡å®ä¾åæ¹å¼**ï¼æä»¬é常æç¨å°çåå»ºå¯¹è±¡çæ¹å¼ï¼ä»æ¬è´¨ä¸æ¥è®²ï¼é½æ¯éè¿ new æºå¶æ¥å®ç°å¯¹è±¡çå建ã使¯ï¼new æºå¶æä¸ªç¹ç¹å°±æ¯å½ç±»åªæä¾æåçæé 彿°ä¸æ æ¾ç¤ºå£°ææ åæé 彿°æ¶ï¼åå¿ é¡»ä½¿ç¨æåæé 彿°è¿è¡å¯¹è±¡æé ï¼èä½¿ç¨æåæé 彿°æ¶ï¼å¿ é¡»ä¼ éç¸åºä¸ªæ°çåæ°æè½å®æå¯¹è±¡å®ä¾åã - **é常è§çå®ä¾åæ¹å¼**ï¼è Unsafe ä¸æä¾ allocateInstance æ¹æ³ï¼ä» éè¿ Class 对象就å¯ä»¥å建æ¤ç±»çå®ä¾å¯¹è±¡ï¼èä¸ä¸éè¦è°ç¨å ¶æé 彿°ãåå§å代ç ãJVM å®å ¨æ£æ¥çã宿å¶ä¿®é¥°ç¬¦æ£æµï¼ä¹å°±æ¯å³ä½¿æé 卿¯ private 修饰çä¹è½éè¿æ¤æ¹æ³å®ä¾åï¼åªéæç±»å¯¹è±¡å³å¯å建ç¸åºç对象ãç±äºè¿ç§ç¹æ§ï¼allocateInstance å¨ java.lang.invokeãObjenesisï¼æä¾ç»è¿ç±»æé å¨çå¯¹è±¡çææ¹å¼ï¼ãGsonï¼ååºååæ¶ç¨å°ï¼ä¸é½æç¸åºçåºç¨ã ### æ°ç»æä½ #### ä»ç» `arrayBaseOffset` ä¸ `arrayIndexScale` è¿ä¸¤ä¸ªæ¹æ³é åèµ·æ¥ä½¿ç¨ï¼å³å¯å®ä½æ°ç»ä¸æ¯ä¸ªå ç´ å¨å åä¸çä½ç½®ã ```java //è¿åæ°ç»ä¸ç¬¬ä¸ä¸ªå ç´ çåç§»å°å public native int arrayBaseOffset(Class> arrayClass); //è¿åæ°ç»ä¸ä¸ä¸ªå ç´ å ç¨çå¤§å° public native int arrayIndexScale(Class> arrayClass); ``` #### å ¸ååºç¨ è¿ä¸¤ä¸ªä¸æ°æ®æä½ç¸å ³çæ¹æ³ï¼å¨ `java.util.concurrent.atomic` å ä¸ç `AtomicIntegerArray`ï¼å¯ä»¥å®ç°å¯¹ `Integer` æ°ç»ä¸æ¯ä¸ªå ç´ çååæ§æä½ï¼ä¸æå ¸åçåºç¨ï¼å¦ä¸å¾ `AtomicIntegerArray` æºç æç¤ºï¼éè¿ `Unsafe` ç `arrayBaseOffset`ã`arrayIndexScale` åå«è·åæ°ç»é¦å ç´ çåç§»å°å `base` åå个å ç´ å¤§å°å å `scale` ãåç»ç¸å ³ååæ§æä½ï¼åä¾èµäºè¿ä¸¤ä¸ªå¼è¿è¡æ°ç»ä¸å ç´ çå®ä½ï¼å¦ä¸å¾äºæç¤ºç `getAndAdd` æ¹æ³å³éè¿ `checkedByteOffset` æ¹æ³è·åææ°ç»å ç´ çåç§»å°åï¼èåéè¿ CAS å®ç°ååæ§æä½ã  ### CAS æä½ #### ä»ç» è¿é¨å主è¦ä¸º CAS ç¸å ³æä½çæ¹æ³ã ```java /** * CAS * @param o å å«è¦ä¿®æ¹fieldç对象 * @param offset å¯¹è±¡ä¸æfieldçåç§»é * @param expected ææå¼ * @param update æ´æ°å¼ * @return true | false */ public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object update); public final native boolean compareAndSwapInt(Object o, long offset, int expected,int update); public final native boolean compareAndSwapLong(Object o, long offset, long expected, long update); ``` **ä»ä¹æ¯ CAS?** CAS 峿¯è¾å¹¶æ¿æ¢ï¼Compare And Swap)ï¼æ¯å®ç°å¹¶åç®æ³æ¶å¸¸ç¨å°çä¸ç§ææ¯ãCAS æä½å å«ä¸ä¸ªæä½æ°ââå åä½ç½®ã颿åå¼åæ°å¼ãæ§è¡ CAS æä½çæ¶åï¼å°å åä½ç½®çå¼ä¸é¢æå弿¯è¾ï¼å¦æç¸å¹é ï¼é£ä¹å¤çå¨ä¼èªå¨å°è¯¥ä½ç½®å¼æ´æ°ä¸ºæ°å¼ï¼å¦åï¼å¤çå¨ä¸å任使ä½ãæä»¬é½ç¥éï¼CAS æ¯ä¸æ¡ CPU çååæä»¤ï¼cmpxchg æä»¤ï¼ï¼ä¸ä¼é ææè°çæ°æ®ä¸ä¸è´é®é¢ï¼`Unsafe` æä¾ç CAS æ¹æ³ï¼å¦ `compareAndSwapXXX`ï¼åºå±å®ç°å³ä¸º CPU æä»¤ `cmpxchg` ã #### å ¸ååºç¨ å¨ JUC å çå¹¶åå·¥å ·ç±»ä¸å¤§éå°ä½¿ç¨äº CAS æä½ï¼åå¨åé¢ä»ç»`synchronized`å`AQS`çæç« ä¸ä¹å¤æ¬¡æå°äº CASï¼å ¶ä½ä¸ºä¹è§éå¨å¹¶åå·¥å ·ç±»ä¸å¹¿æ³åæ¥äºä½ç¨ãå¨ `Unsafe` ç±»ä¸ï¼æä¾äº`compareAndSwapObject`ã`compareAndSwapInt`ã`compareAndSwapLong`æ¹æ³æ¥å®ç°ç对`Object`ã`int`ã`long`ç±»åç CAS æä½ã以`compareAndSwapInt`æ¹æ³ä¸ºä¾ï¼ ```java public final native boolean compareAndSwapInt(Object o, long offset,int expected,int x); ``` åæ°ä¸`o`为éè¦æ´æ°ç对象ï¼`offset`æ¯å¯¹è±¡`o`䏿´å½¢å段çåç§»éï¼å¦æè¿ä¸ªå段çå¼ä¸`expected`ç¸åï¼åå°å段çå¼è®¾ä¸º`x`è¿ä¸ªæ°å¼ï¼å¹¶ä¸æ¤æ´æ°æ¯ä¸å¯è¢«ä¸æçï¼ä¹å°±æ¯ä¸ä¸ªååæä½ãä¸é¢æ¯ä¸ä¸ªä½¿ç¨`compareAndSwapInt`çä¾åï¼ ```java private volatile int a; public static void main(String[] args){ CasTest casTest=new CasTest(); new Thread(()->{ for (int i = 1; i < 5; i++) { casTest.increment(i); System.out.print(casTest.a+" "); } }).start(); new Thread(()->{ for (int i = 5 ; i <10 ; i++) { casTest.increment(i); System.out.print(casTest.a+" "); } }).start(); } private void increment(int x){ while (true){ try { long fieldOffset = unsafe.objectFieldOffset(CasTest.class.getDeclaredField("a")); if (unsafe.compareAndSwapInt(this,fieldOffset,x-1,x)) break; } catch (NoSuchFieldException e) { e.printStackTrace(); } } } ``` è¿è¡ä»£ç ä¼ä¾æ¬¡è¾åºï¼ ``` 1 2 3 4 5 6 7 8 9 ``` å¨ä¸é¢çä¾åä¸ï¼ä½¿ç¨ä¸¤ä¸ªçº¿ç¨å»ä¿®æ¹`int`å屿§`a`çå¼ï¼å¹¶ä¸åªæå¨`a`çå¼çäºä¼ å ¥çåæ°`x`å䏿¶ï¼æä¼å°`a`çå¼å为`x`ï¼ä¹å°±æ¯å®ç°å¯¹`a`çå ä¸çæä½ãæµç¨å¦ä¸æç¤ºï¼  éè¦æ³¨æçæ¯ï¼å¨è°ç¨`compareAndSwapInt`æ¹æ³åï¼ä¼ç´æ¥è¿å`true`æ`false`çä¿®æ¹ç»æï¼å æ¤éè¦æä»¬å¨ä»£ç 䏿卿·»å èªæçé»è¾ãå¨`AtomicInteger`ç±»ç设计ä¸ï¼ä¹æ¯éç¨äºå°`compareAndSwapInt`çç»æä½ä¸ºå¾ªç¯æ¡ä»¶ï¼ç´è³ä¿®æ¹æåæéåºæ»å¾ªç¯çæ¹å¼æ¥å®ç°çååæ§çèªå¢æä½ã ### 线ç¨è°åº¦ #### ä»ç» `Unsafe` ç±»ä¸æä¾äº`park`ã`unpark`ã`monitorEnter`ã`monitorExit`ã`tryMonitorEnter`æ¹æ³è¿è¡çº¿ç¨è°åº¦ã ```java //åæ¶é»å¡çº¿ç¨ public native void unpark(Object thread); //é»å¡çº¿ç¨ public native void park(boolean isAbsolute, long time); //è·å¾å¯¹è±¡éï¼å¯éå ¥éï¼ @Deprecated public native void monitorEnter(Object o); //éæ¾å¯¹è±¡é @Deprecated public native void monitorExit(Object o); //å°è¯è·å对象é @Deprecated public native boolean tryMonitorEnter(Object o); ``` æ¹æ³ `park`ã`unpark` å³å¯å®ç°çº¿ç¨çæèµ·ä¸æ¢å¤ï¼å°ä¸ä¸ªçº¿ç¨è¿è¡æèµ·æ¯éè¿ `park` æ¹æ³å®ç°çï¼è°ç¨ `park` æ¹æ³åï¼çº¿ç¨å°ä¸ç´é»å¡ç´å°è¶ æ¶æè ä¸æçæ¡ä»¶åºç°ï¼`unpark` å¯ä»¥ç»æ¢ä¸ä¸ªæèµ·ç线ç¨ï¼ä½¿å ¶æ¢å¤æ£å¸¸ã æ¤å¤ï¼`Unsafe` æºç ä¸`monitor`ç¸å ³çä¸ä¸ªæ¹æ³å·²ç»è¢«æ 记为`deprecated`ï¼ä¸å»ºè®®è¢«ä½¿ç¨ï¼ ```java //è·å¾å¯¹è±¡é @Deprecated public native void monitorEnter(Object var1); //éæ¾å¯¹è±¡é @Deprecated public native void monitorExit(Object var1); //å°è¯è·å¾å¯¹è±¡é @Deprecated public native boolean tryMonitorEnter(Object var1); ``` `monitorEnter`æ¹æ³ç¨äºè·å¾å¯¹è±¡éï¼`monitorExit`ç¨äºéæ¾å¯¹è±¡éï¼å¦æå¯¹ä¸ä¸ªæ²¡æè¢«`monitorEnter`å éç对象æ§è¡æ¤æ¹æ³ï¼ä¼æåº`IllegalMonitorStateException`å¼å¸¸ã`tryMonitorEnter`æ¹æ³å°è¯è·å对象éï¼å¦ææååè¿å`true`ï¼åä¹è¿å`false`ã #### å ¸ååºç¨ Java éå忥卿¡æ¶çæ ¸å¿ç±» `AbstractQueuedSynchronizer` (AQS)ï¼å°±æ¯éè¿è°ç¨`LockSupport.park()`å`LockSupport.unpark()`å®ç°çº¿ç¨çé»å¡åå¤éçï¼è `LockSupport` ç `park`ã`unpark` æ¹æ³å®é æ¯è°ç¨ `Unsafe` ç `park`ã`unpark` æ¹å¼å®ç°çã ```java public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, 0L); setBlocker(t, null); } public static void unpark(Thread thread) { if (thread != null) UNSAFE.unpark(thread); } ``` `LockSupport` ç`park`æ¹æ³è°ç¨äº `Unsafe` ç`park`æ¹æ³æ¥é»å¡å½å线ç¨ï¼æ¤æ¹æ³å°çº¿ç¨é»å¡åå°±ä¸ä¼ç»§ç»å¾åæ§è¡ï¼ç´å°æå ¶ä»çº¿ç¨è°ç¨`unpark`æ¹æ³å¤éå½å线ç¨ãä¸é¢çä¾å对 `Unsafe` çè¿ä¸¤ä¸ªæ¹æ³è¿è¡æµè¯ï¼ ```java public static void main(String[] args) { Thread mainThread = Thread.currentThread(); new Thread(()->{ try { TimeUnit.SECONDS.sleep(5); System.out.println("subThread try to unpark mainThread"); unsafe.unpark(mainThread); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); System.out.println("park main mainThread"); unsafe.park(false,0L); System.out.println("unpark mainThread success"); } ``` ç¨åºè¾åºä¸ºï¼ ``` park main mainThread subThread try to unpark mainThread unpark mainThread success ``` ç¨åºè¿è¡çæµç¨ä¹æ¯è¾å®¹æçæï¼å线ç¨å¼å§è¿è¡åå è¿è¡ç¡ç ï¼ç¡®ä¿ä¸»çº¿ç¨è½å¤è°ç¨`park`æ¹æ³é»å¡èªå·±ï¼å线ç¨å¨ç¡ç 5 ç§åï¼è°ç¨`unpark`æ¹æ³å¤é主线ç¨ï¼ä½¿ä¸»çº¿ç¨è½ç»§ç»å䏿§è¡ãæ´ä¸ªæµç¨å¦ä¸å¾æç¤ºï¼  ### Class æä½ #### ä»ç» `Unsafe` 对`Class`çç¸å ³æä½ä¸»è¦å æ¬ç±»å è½½åéæåéçæä½æ¹æ³ã **éæå±æ§è¯»åç¸å ³çæ¹æ³** ```java //è·åéæå±æ§çåç§»é public native long staticFieldOffset(Field f); //è·åéæå±æ§ç对象æé public native Object staticFieldBase(Field f); //å¤æç±»æ¯å¦éè¦åå§åï¼ç¨äºè·åç±»çéæå±æ§åè¿è¡æ£æµï¼ public native boolean shouldBeInitialized(Class> c); ``` å建ä¸ä¸ªå å«éæå±æ§çç±»ï¼è¿è¡æµè¯ï¼ ```java @Data public class User { public static String name="Hydra"; int age; } private void staticTest() throws Exception { User user=new User(); // ä¹å¯ä»¥ç¨ä¸é¢çè¯å¥è§¦åç±»åå§å // 1. // unsafe.ensureClassInitialized(User.class); // 2. // System.out.println(User.name); System.out.println(unsafe.shouldBeInitialized(User.class)); Field sexField = User.class.getDeclaredField("name"); long fieldOffset = unsafe.staticFieldOffset(sexField); Object fieldBase = unsafe.staticFieldBase(sexField); Object object = unsafe.getObject(fieldBase, fieldOffset); System.out.println(object); } ``` è¿è¡ç»æï¼ ``` falseHydra ``` å¨ `Unsafe` ç对象æä½ä¸ï¼æä»¬å¦ä¹ äºéè¿`objectFieldOffset`æ¹æ³è·åå¯¹è±¡å±æ§åç§»éå¹¶åºäºå®å¯¹åéçå¼è¿è¡ååï¼ä½æ¯å®ä¸éç¨äºç±»ä¸çéæå±æ§ï¼è¿æ¶åå°±éè¦ä½¿ç¨`staticFieldOffset`æ¹æ³ãå¨ä¸é¢ç代ç ä¸ï¼åªæå¨è·å`Field`对象çè¿ç¨ä¸ä¾èµå°äº`Class`ï¼èè·åéæåéç屿§æ¶ä¸åä¾èµäº`Class`ã å¨ä¸é¢ç代ç ä¸é¦å å建ä¸ä¸ª`User`对象ï¼è¿æ¯å ä¸ºå¦æä¸ä¸ªç±»æ²¡æè¢«åå§åï¼é£ä¹å®çéæå±æ§ä¹ä¸ä¼è¢«åå§åï¼æåè·åçåæ®µå±æ§å°æ¯`null`ãæä»¥å¨è·åéæå±æ§åï¼éè¦è°ç¨`shouldBeInitialized`æ¹æ³ï¼å¤æå¨è·å忝å¦éè¦åå§åè¿ä¸ªç±»ã妿å é¤å建 User 对象çè¯å¥ï¼è¿è¡ç»æä¼åä¸ºï¼ ``` truenull ``` **使ç¨`defineClass`æ¹æ³å 许ç¨åºå¨è¿è¡æ¶å¨æå°å建ä¸ä¸ªç±»** ```java public native Class> defineClass(String name, byte[] b, int off, int len, ClassLoader loader,ProtectionDomain protectionDomain); ``` å¨å®é 使ç¨è¿ç¨ä¸ï¼å¯ä»¥åªä¼ å ¥åèæ°ç»ãèµ·å§åèç䏿 以å读åçåèé¿åº¦ï¼é»è®¤æ åµä¸ï¼ç±»å è½½å¨ï¼`ClassLoader`ï¼åä¿æ¤åï¼`ProtectionDomain`ï¼æ¥æºäºè°ç¨æ¤æ¹æ³çå®ä¾ãä¸é¢çä¾åä¸å®ç°äºåç¼è¯çæåç class æä»¶çåè½ï¼ ```java private static void defineTest() { String fileName="F:\\workspace\\unsafe-test\\target\\classes\\com\\cn\\model\\User.class"; File file = new File(fileName); try(FileInputStream fis = new FileInputStream(file)) { byte[] content=new byte[(int)file.length()]; fis.read(content); Class clazz = unsafe.defineClass(null, content, 0, content.length, null, null); Object o = clazz.newInstance(); Object age = clazz.getMethod("getAge").invoke(o, null); System.out.println(age); } catch (Exception e) { e.printStackTrace(); } } ``` å¨ä¸é¢ç代ç ä¸ï¼é¦å 读åäºä¸ä¸ª`class`æä»¶å¹¶éè¿æä»¶æµå°å®è½¬å为åèæ°ç»ï¼ä¹å使ç¨`defineClass`æ¹æ³å¨æçå建äºä¸ä¸ªç±»ï¼å¹¶å¨åç»å®æäºå®çå®ä¾åå·¥ä½ï¼æµç¨å¦ä¸å¾æç¤ºï¼å¹¶ä¸éè¿è¿ç§æ¹å¼å建çç±»ï¼ä¼è·³è¿ JVM çææå®å ¨æ£æ¥ã  é¤äº`defineClass`æ¹æ³å¤ï¼Unsafe è¿æä¾äºä¸ä¸ª`defineAnonymousClass`æ¹æ³ï¼ ```java public native Class> defineAnonymousClass(Class> hostClass, byte[] data, Object[] cpPatches); ``` 使ç¨è¯¥æ¹æ³å¯ä»¥ç¨æ¥å¨æçå建ä¸ä¸ªå¿åç±»ï¼å¨`Lambda`表达å¼ä¸å°±æ¯ä½¿ç¨ ASM 卿çæåèç ï¼ç¶åå©ç¨è¯¥æ¹æ³å®ä¹å®ç°ç¸åºç彿°å¼æ¥å£çå¿åç±»ãå¨ JDK 15 åå¸çæ°ç¹æ§ä¸ï¼å¨éèç±»ï¼`Hidden classes`ï¼ä¸æ¡ä¸ï¼æåºå°å¨æªæ¥ççæ¬ä¸å¼ç¨ `Unsafe` ç`defineAnonymousClass`æ¹æ³ã #### å ¸ååºç¨ Lambda 表达å¼å®ç°éè¦ä¾èµ `Unsafe` ç `defineAnonymousClass` æ¹æ³å®ä¹å®ç°ç¸åºç彿°å¼æ¥å£çå¿åç±»ã ### ç³»ç»ä¿¡æ¯ #### ä»ç» è¿é¨åå å«ä¸¤ä¸ªè·åç³»ç»ç¸å ³ä¿¡æ¯çæ¹æ³ã ```java //è¿åç³»ç»æéç大å°ãè¿åå¼ä¸º4ï¼32ä½ç³»ç»ï¼æ 8ï¼64ä½ç³»ç»ï¼ã public native int addressSize(); //å å页ç大å°ï¼æ¤å¼ä¸º2ç广¬¡æ¹ã public native int pageSize(); ``` #### å ¸ååºç¨ è¿ä¸¤ä¸ªæ¹æ³çåºç¨åºæ¯æ¯è¾å°ï¼å¨`java.nio.Bits`ç±»ä¸ï¼å¨ä½¿ç¨`pageCount`è®¡ç®æéçå åé¡µçæ°éæ¶ï¼è°ç¨äº`pageSize`æ¹æ³è·åå å页ç大å°ãå¦å¤ï¼å¨ä½¿ç¨`copySwapMemory`æ¹æ³æ·è´å åæ¶ï¼è°ç¨äº`addressSize`æ¹æ³ï¼æ£æµ 32 ä½ç³»ç»çæ åµã ## æ»ç» 卿¬æä¸ï¼æä»¬é¦å ä»ç»äº `Unsafe` çåºæ¬æ¦å¿µãå·¥ä½åçï¼å¹¶å¨æ¤åºç¡ä¸ï¼å¯¹å®ç API è¿è¡äºè¯´æä¸å®è·µãç¸ä¿¡å¤§å®¶éè¿è¿ä¸è¿ç¨ï¼è½å¤åç° `Unsafe` 卿äºåºæ¯ä¸ï¼ç¡®å®è½å¤ä¸ºæä»¬æä¾ç¼ç¨ä¸ç便å©ã使¯åå°å¼å¤´çè¯é¢ï¼å¨ä½¿ç¨è¿äºä¾¿å©æ¶ï¼ç¡®å®åå¨çä¸äºå®å ¨ä¸ç鿣ï¼å¨æçæ¥ï¼ä¸é¡¹ææ¯å ·æä¸å®å ¨å ç´ å¹¶ä¸å¯æï¼å¯æçæ¯å®å¨ä½¿ç¨è¿ç¨ä¸è¢«æ»¥ç¨ã尽管ä¹åæä¼ è¨è¯´ä¼å¨ Java9 ä¸ç§»é¤ `Unsafe` ç±»ï¼ä¸è¿å®è¿æ¯ç §æ ·å·²ç»åæ´»å°äº Java16ãæç §åå¨å³åççé»è¾ï¼åªè¦ä½¿ç¨å¾å½ï¼å®è¿æ¯è½ç»æä»¬å¸¦æ¥ä¸å°ç帮å©ï¼å æ¤æåè¿æ¯å»ºè®®å¤§å®¶ï¼å¨ä½¿ç¨ `Unsafe` çè¿ç¨ä¸ä¸å®è¦åå°ä½¿ç¨è°¨æ 使ç¨ãé¿å 滥ç¨ã