成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

微博二面:所有對象都一定被分配在堆中么?

開發 前端
在一般應用中,完全不會逃逸的局部對象和不會逃逸出線程的對象所占的比例是很大的,如果能使用棧上分配,那大量的對象就會隨著方法的結束而自動銷毀了,垃圾收集子系統的壓力將會下降很多。

什么是逃逸分析

所謂逃逸,包括方法逃逸和線程逃逸,線程逃逸的逃逸程度高于方法逃逸(線程逃逸 > 方法逃逸):

當一個對象在方法里面被定義后,它如果被外部方法所引用(例如作為調用參數傳遞到其他方法中),這種稱為方法逃逸;

可能被外部其他線程訪問到,譬如賦值給可以在其他線程中訪問的實例變量,這種稱為線程逃逸;

this 引用逃逸就是一種線程逃逸:在構造器構造還未徹底完成前(即實例初始化階段還未完成),將自身 this 引用向外拋出并被其他線程復制(訪問)了該引用,那么其他線程就可能會訪問到該還未被初始化的變量。

舉個例子:

public class FinalReferenceEscapeTest {    
 final int i;    
 static FinalReferenceEscapeTest obj;    
 public FinalReferenceEscapeTest () {        
  i = 1;                   // 1. 寫 final 域
  obj = this;              // 2. this 引用在此 "逸出"
 } 

// 線程 A
 public static void writer() { 
  new FinalReferenceEscapeExample(); 
 } 

// 線程  B
 public static void reader() { 
  if (obj != null) {      // 3 
   int temp = obj.i;   // 4 
  } 
 }
}

假設一個線程 A 執行 writer() 方法,另一個線程 B 執行 reader() 方法。這里的操作 2 將自身 this 引用向外拋出,使得 FinalReferenceEscapeTest 對象還未完成構造前就為其他線程可見。

有的同學可能會問,這個操作 2 不是在構造函數的最后一步嗎,它執行完構造函數也執行完了,對象不就已經完成構造了嗎?

But 這里的操作 1 和操作 2 之間可能被重排序。如下圖所示,線程 B 不能正確地讀到 i = 1,而是未初始化的 i = 0:

所以,我們可以得出這樣的結論:在構造函數返回前,被構造對象的引用不能為其他線程所見,因為此時的各個字段(域)可能還沒有被初始化。

如果虛擬機能夠確定一個對象不會發生方法逃逸和線程逃逸,或者逃逸程度比較低(只發生方法逃逸,不發生線程逃逸),則(JIT 即時編譯器)可以為這個對象實例采取不同程度的優化,比如鎖消除 Lock Elimination(也稱為 “同步消除 Synchronization Elimination”)、還有 棧上分配(Stack Allocations) 和 標量替換(Scalar Replacement)等

棧上分配

棧上分配(Stack Allocations)是 JIT 即時編譯器的一項優化技術:如果確定一個對象不會逃逸出線程之外(不發生逃逸或逃逸程度較低 - 方法逃逸),那讓這個對象在棧(線程私有)上分配內存將會是一個很不錯的主意,對象所占用的內存空間就可以隨棧幀出棧而銷毀。

在一般應用中,完全不會逃逸的局部對象和不會逃逸出線程的對象所占的比例是很大的,如果能使用棧上分配,那大量的對象就會隨著方法的結束而自動銷毀了,垃圾收集子系統的壓力將會下降很多。

示例代碼:

public class StackAllocationExample {
    private static final int MAX = 10000000;
    
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < MAX; i++) {
            allocateOnStack();
        }
        long end = System.currentTimeMillis();
        System.out.println("Time taken: " + (end - start) + "ms");
    }
    
    private static void allocateOnStack() {
        Point p = new Point();
        p.x = 1;
        p.y = 2;
    }
    
    private static class Point {
        int x;
        int y;
    }
}

在這個示例代碼中,我們定義了一個私有的靜態內部類 Point,它包含兩個 int 類型的成員變量 x 和 y。在 main 方法中,我們循環調用 allocateOnStack 方法,該方法內部創建一個 Point 對象并將其成員變量賦值為 1 和 2。由于 allocateOnStack 方法沒有返回 Point 對象,換言之 Point 對象是不會被暴露給其他線程的,即不會發生線程逃逸,因此編譯器可以將該對象分配在棧上而不是堆上。

責任編輯:武曉燕 來源: 飛天小牛肉
相關推薦

2023-10-14 17:49:25

Java存儲

2024-08-05 09:27:48

算法死鎖場景

2020-11-23 07:08:17

JVM逃逸元空間

2013-09-03 09:09:30

大數據

2010-05-07 19:15:18

Oracle flas

2019-05-05 06:08:17

DDoS網絡攻擊僵尸網絡

2023-03-06 00:13:58

IOT內存物聯網

2020-08-30 14:31:40

Python編程語言開發

2021-06-15 23:04:17

Localhost域名網絡

2021-10-18 08:41:20

Redis ACID事務

2018-01-02 10:46:24

微信騰訊表情

2021-09-28 07:12:09

函數內存

2024-12-13 15:37:55

2018-05-15 16:01:53

對象內存JVM

2015-06-17 11:18:01

WiFi

2015-03-30 10:48:17

大數據大數據處理Hadoop

2019-01-21 08:20:17

通信4G5G

2021-02-26 09:04:22

數組ArrayListHashMap

2011-04-07 09:32:49

遞歸

2017-09-28 08:35:35

前端HTML標簽大全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线视频亚洲 | 国产蜜臀 | 蜜桃免费av| 天堂视频一区 | 精精国产视频 | 国产精品久久久久久婷婷天堂 | 国产在线高清 | 中文字幕av网址 | 日p视频免费看 | 国产精品明星裸体写真集 | www.99热这里只有精品 | 国产色爽 | 久久99精品久久久久蜜桃tv | 日日草天天干 | 色中文在线 | 4hu最新网址 | 欧美一区二区三区日韩 | av在线免费网 | 欧美精品福利 | 成人3d动漫一区二区三区91 | 精品九九九 | 日韩在线观看网站 | 日韩欧美在线视频一区 | 亚洲欧美日韩一区 | www.日韩av.com | 久久国产视频网站 | 久久精品国产亚洲夜色av网站 | 日韩性在线 | 成人一区二区在线 | 久久久久久综合 | 精品久久久久久亚洲精品 | 完全免费在线视频 | 国产成人精品一区二区三 | 国产一区二区成人 | 国产日韩欧美 | 成人av片在线观看 | 精品国产一区二区三区久久影院 | 欧美亚洲成人网 | 亚洲人成人一区二区在线观看 | 日韩精品一区二区三区 | 先锋影音资源网站 |