国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JVM解剖公園

imingyu / 486人閱讀

摘要:為此,引入轉(zhuǎn)換查找緩沖緩存最近的轉(zhuǎn)換記錄。這個(gè)優(yōu)化技術(shù),可以看到將原本對(duì)對(duì)象的字段訪問,替換為一個(gè)局部變量的訪問。當(dāng)所有線程都在已知的位置停止的時(shí)候,被認(rèn)為是到達(dá)了安全點(diǎn)。檢查安全點(diǎn)請(qǐng)求的代碼

1、JVM鎖粗化和循環(huán)
原文標(biāo)題:JVM Anatomy Quark #1: Lock Coarsening and Loops

眾所周知Hotsport編譯器會(huì)進(jìn)行JVM鎖粗化和優(yōu)化,它將相鄰的鎖區(qū)塊進(jìn)行合并,有效減少鎖的的占用成本,類似

synchronized (obj) {
  // statements 1
}
synchronized (obj) {
  // statements 2
}

優(yōu)化成

synchronized (obj) {
  // statements 1
  // statements 2
}

那么在循環(huán)體中是否也會(huì)進(jìn)行相同的優(yōu)化?類似

for (...) {
  synchronized (obj) {
    // something
  }
}

優(yōu)化成

synchronized (this) {
  for (...) {
     // something
  }
}   

實(shí)際上是不會(huì)的,理論上來說是可以的,這有點(diǎn)像針對(duì)鎖的循環(huán)無關(guān)代碼外提。然而如此優(yōu)化的缺點(diǎn)是將鎖的粒度增加太多,線程在執(zhí)行循環(huán)時(shí)將會(huì)長(zhǎng)時(shí)間獨(dú)占鎖

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

2、透明大頁
原文標(biāo)題:JVM Anatomy Quark #2: Transparent Huge Pages

進(jìn)程都擁有自己的虛擬內(nèi)存空間,虛擬內(nèi)存空間會(huì)映射到實(shí)際內(nèi)存。例如,兩個(gè)進(jìn)程可以在相同的虛擬地址 0x42424242 中存儲(chǔ)不同數(shù)據(jù),這些數(shù)據(jù)實(shí)際存放在不同的物理內(nèi)存中。當(dāng)程序訪問該地址時(shí),通過某種機(jī)制會(huì)把虛擬地址轉(zhuǎn)換成實(shí)際物理地址

這個(gè)過程一般通過由操作系統(tǒng)維護(hù)的頁表實(shí)現(xiàn),硬件通過"遍歷頁表"進(jìn)行地址轉(zhuǎn)換。雖然以頁面為單位進(jìn)行地址轉(zhuǎn)換更容易,但由于每次訪問內(nèi)存都會(huì)發(fā)生地址轉(zhuǎn)換會(huì)帶來不小開銷。為此,引入TLB(轉(zhuǎn)換查找緩沖)緩存最近的轉(zhuǎn)換記錄。TLB要求至少要與 L1 緩存一樣快,因此通常緩存少于100條。對(duì)工作負(fù)載較大的情況,TLB缺失和由此引發(fā)的頁表遍歷需要很多時(shí)間

TLB容量比較小,但是我們可以將地址轉(zhuǎn)換的頁面容量增大,這個(gè)可以借助系統(tǒng)內(nèi)核的透明大頁機(jī)制輕松做到,那這樣是否會(huì)對(duì)性能有所幫助呢?

實(shí)際上它能有效提高應(yīng)用程序性能,特別是當(dāng)程序擁有大量數(shù)據(jù)和堆棧時(shí)

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

3、GC設(shè)計(jì)和停頓

原文標(biāo)題:JVM Anatomy Quark #3: GC Design and Pauses

常見GC算法如下所示,其中黃色為stop-the-world階段,綠色為并發(fā)階段

需要注意不同收集器在常規(guī)GC循環(huán)中何時(shí)會(huì)暫停

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

4、TLAB內(nèi)存分配
原文標(biāo)題:JVM Anatomy Quark #4: TLAB allocation

本小節(jié)將揭曉,什么是Bump-the-pointer技術(shù)跟蹤?什么是TLAB內(nèi)存分配?

Bump-the-pointer技術(shù)跟蹤在eden區(qū)創(chuàng)建的最后一件對(duì)象,最后該對(duì)象會(huì)放在eden頂部,之后再創(chuàng)建對(duì)象時(shí),只需要檢查最后一個(gè)對(duì)象就可以知道eden空間容量是否足夠,但是在多線程環(huán)境中就會(huì)出現(xiàn)問題,不過加鎖同步開銷太大,于是提出TLAB

TLAB(Thread-local allocation buffer)緩沖區(qū),特點(diǎn)是每個(gè)線程獨(dú)享一份,也就意味著不存在數(shù)據(jù)共享也就不需要加鎖同步,同時(shí)它結(jié)合了Bump-the-pointer跟蹤技術(shù)實(shí)現(xiàn)快速的對(duì)象分配

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

5、TLAB與堆可解析性

原文標(biāo)題:JVM Anatomy Quark #5: TLABs and Heap Parsability

好的垃圾回收器通常會(huì)保證堆的可解析性,意味著它不需要復(fù)雜的數(shù)據(jù)結(jié)構(gòu)也能以某種方式解析成對(duì)象或者字段。雖然嚴(yán)格來說,它在分配周期中并不是始終以對(duì)象流的方式存在,但是它使得GC實(shí)現(xiàn)、測(cè)試、調(diào)戲變得輕易

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

6、創(chuàng)建對(duì)象階段
原文標(biāo)題:JVM Anatomy Quark #6: New Object Stages

你可能聽說過分配并不是初始化。但是 Java 有構(gòu)造方法!構(gòu)造方法是分配?還是初始化?

Java語言中的new對(duì)應(yīng)很多字節(jié)碼指令,比如

public Object t() {
  return new Object();
}

編譯為

 public java.lang.Object t();
    descriptor: ()Ljava/lang/Object;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: new           #4                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."":()V
         7: areturn

給人感覺是,new關(guān)鍵會(huì)執(zhí)行分配資源和系統(tǒng)初始化,同時(shí)調(diào)用構(gòu)造方法執(zhí)行用戶初始化,但是聰明的虛擬機(jī)會(huì)進(jìn)行優(yōu)化,比如在構(gòu)造方法執(zhí)行完成之前觀察對(duì)象使用情況然后選擇性合并任務(wù)

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

7、初始化開銷
原文標(biāo)題:JVM Anatomy Quark #7: Initialization Costs

初始化對(duì)象或者數(shù)組是實(shí)例化過程中最主要的開銷,使用TLAB分配,對(duì)象或者數(shù)據(jù)初始化的開銷取決于元數(shù)據(jù)寫入和內(nèi)容的初始化

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

8、局部變量可用性
原文標(biāo)題:JVM Anatomy Quark #8: Local Variable Reachability

離開了當(dāng)前作用域,存儲(chǔ)在局部變量中的引用才會(huì)被回收,這種說法正確嗎?在Java中并非如此,Java局部變量的可用性不由代碼塊決定,而與最后一次使用有關(guān),并且可能會(huì)持續(xù)到最后一次使用為止。使用像finalizer、強(qiáng)引用、弱引用、虛引用這樣的方法通知對(duì)象不可達(dá),會(huì)受到“提前檢查”優(yōu)化帶來的影響,使得代碼塊還沒有結(jié)束變量可能已不可用,這是一種很好的特性,使得GC能提前回收掉本地分配的大量緩存

當(dāng)然如果想獲得C++編程那種代碼塊結(jié)束時(shí)才釋放的特性,你可以使用try-finally

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

9、JNI 臨界區(qū) 與 GC 鎖
原文標(biāo)題:JVM Anatomy Quark #9: JNI Critical and GC Locker

10、String中的intern方法
原文標(biāo)題:JVM Anatomy Quark #10: String.intern()

我們知道intern方法會(huì)從字符串常量池中查詢當(dāng)前字符串是否存在,若不存在就會(huì)將當(dāng)前字符串放入常量池中,從而使得字符串對(duì)象被緩存了一樣

JAVA使用JNI調(diào)用c++實(shí)現(xiàn)的StringTable的intern方法, StringTable的intern方法跟Java中的HashMap的實(shí)現(xiàn)是差不多的, 只是不能自動(dòng)擴(kuò)容。默認(rèn)大小是1009

要注意的是,String的String Pool是一個(gè)固定大小的Hashtable,默認(rèn)值大小長(zhǎng)度是1009,如果放進(jìn)String Pool的String非常多,就會(huì)造成Hash沖突嚴(yán)重,從而導(dǎo)致鏈表會(huì)很長(zhǎng),而鏈表長(zhǎng)了后直接造成的影響就是調(diào)用String.intern時(shí)性能會(huì)大幅下降

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

11、移動(dòng)GC與局部性
原文標(biāo)題:JVM Anatomy Quark #11: Moving GC and Locality

標(biāo)記-壓縮回收器可以保持堆中對(duì)象的分配順序,也可以對(duì)其任意重排。雖然任意順序能夠比其他標(biāo)記-壓縮回收器速度更快,也不會(huì)帶來空間開銷,但是會(huì)破壞應(yīng)用線程的局部性

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

12、本地內(nèi)存跟蹤
原文標(biāo)題:JVM Anatomy Quark #12: Native Memory Tracking

JVM的默認(rèn)配置通常是為長(zhǎng)時(shí)間運(yùn)行的服務(wù)器應(yīng)用準(zhǔn)備的,包括GC、內(nèi)部數(shù)據(jù)結(jié)構(gòu)的初始大小、堆棧大小等也是如此,而通過NMT探索虛擬機(jī)內(nèi)存分配情況能讓我們立刻知道從哪里入手優(yōu)化應(yīng)用占用的內(nèi)存,同時(shí)非常有助于在應(yīng)用實(shí)際生產(chǎn)環(huán)境中調(diào)整JVM參數(shù)

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

13、屏障
原文標(biāo)題:JVM Anatomy Quark #13: Intergenerational Barriers

GC通常會(huì)有屏障組,即使沒有實(shí)際發(fā)生回收,這些屏障也會(huì)影響應(yīng)用程序的性能。即使串行、并行這樣非常基本的分代收集器,也至少有一個(gè)引用存儲(chǔ)屏障,而像G1這樣更高級(jí)的回收器會(huì)有更復(fù)雜的屏障跟蹤不同區(qū)域間的引用。某些情況下,這種開銷讓人非常痛苦

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

14、常量變量
原文標(biāo)題:JVM Anatomy Quark #14: Constant Variables

停留2秒思考下面的代碼塊會(huì)輸出什么

import java.lang.reflect.Field;

public class ConstantValues {

final int fieldInit = 42;
final int instanceInit;
final int constructor;

{
    instanceInit = 42;
}

public ConstantValues() {
    constructor = 42;
}

static void set(ConstantValues p, String field) throws Exception {
    Field f = ConstantValues.class.getDeclaredField(field);
    f.setAccessible(true);
    f.setInt(p, 9000);
}

public static void main(String... args) throws Exception {
    ConstantValues p = new ConstantValues();

    set(p, "fieldInit");
    set(p, "instanceInit");
    set(p, "constructor");

    System.out.println(p.fieldInit + " " + p.instanceInit + " " + p.constructor);
}

}

正常會(huì)打印出42 9000 9000,也就是說即使通過反射重寫了fieldInt字段的值,我們也無法觀察到最新的值,而更新另外兩個(gè)字段生效了,這個(gè)奇怪結(jié)果的解釋是方法內(nèi)聯(lián)

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

15、即時(shí)常量

編譯器信任static final字段,因?yàn)檫@個(gè)值不依賴特定對(duì)象,而且是不能改變的

https://shipilev.net/jvm/anat...

16、超多態(tài)虛調(diào)用
https://shipilev.net/jvm/anat...

17、信任非靜態(tài)Final字段

原文標(biāo)題:JVM Anatomy Quark #17: Trust Nonstatic Final Fields

   class M {
      final int x;
      M(int x) { this.x = x; }
    }
    
    static final M KNOWN_M = new M(1337);
    
    void work() {
      // We know exactly the slot that holds the variable, can we just
      // inline the value 1337 here?
      return KNOWN_M.x;
    }

上面這段代碼是否會(huì)進(jìn)行方法內(nèi)聯(lián)優(yōu)化呢?實(shí)際上是不會(huì)的,如果要信任實(shí)例final字段,那么必須知道當(dāng)前操作的對(duì)象,然而上面那段代碼是引用關(guān)系

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

18、字面量替換

原文標(biāo)題:JVM Anatomy Quark #18: Scalar Replacement

利用逃逸分析然后編譯器優(yōu)化可以實(shí)現(xiàn)在棧上分配而不是堆上分配,方法退出后直接彈出釋放,無助借助垃圾回收器處理,很神奇,對(duì)嗎?

不過一旦發(fā)生了逃逸現(xiàn)象,我們需要將實(shí)體對(duì)象完整地復(fù)制到堆中。而且由于實(shí)現(xiàn)起來需要更改大量假設(shè)了"對(duì)象只能在堆上分配"的代碼,因?yàn)镠otSpot虛擬機(jī)并沒有采用棧上分配,而是標(biāo)量替換這么一項(xiàng)技術(shù)。這個(gè)優(yōu)化技術(shù),可以看到將原本對(duì)對(duì)象的字段訪問,替換為一個(gè)局部變量的訪問。該對(duì)象沒有被實(shí)際分配,因此和棧上分配一樣,它同樣可以減輕垃圾回收的壓力

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

19、鎖消除
原文標(biāo)題:JVM Anatomy Quark #19: Lock Elision

目前的內(nèi)存模型中,對(duì)不共享的對(duì)象進(jìn)行加鎖操作是無效的,編譯器不會(huì)對(duì)它做任何事情。由于其他線程不能獲取該鎖對(duì)象,因此也無法基于該鎖對(duì)象構(gòu)造兩個(gè)線程之間的happens-before規(guī)則。那么編譯器只需證明鎖對(duì)象不會(huì)發(fā)生逃逸,便可以進(jìn)行鎖消除

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

20、FPU溢出
原文標(biāo)題:JVM Anatomy Quark #20: FPU Spills

寄存器分配器的職責(zé)是,維護(hù)在特定的編譯單元中程序需要的所有操作數(shù)的程序表示,并且映射這些虛操作數(shù)到實(shí)際的機(jī)器寄存器,也就是為它們分配寄存器。在許多真實(shí)的程序中,在給定程序位置,虛操作數(shù)的數(shù)量會(huì)大于可用機(jī)器寄存器的數(shù)量,那么寄存器分配器就需要將某些操作數(shù)放到寄存器之外的其它位置比如放到棧上,這種就稱為FPU溢出,有效緩解了寄存器壓力

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

21、堆內(nèi)存歸還
原文標(biāo)題:JVM Anatomy Quark #21: Heap Uncommit

許多GC已經(jīng)實(shí)現(xiàn)了在合適的時(shí)機(jī)歸還堆內(nèi)存:Shenandoah異步執(zhí)行堆內(nèi)存歸還,即使沒有GC請(qǐng)求;G1在顯式GC請(qǐng)求中執(zhí)行堆內(nèi)存歸還;Serial和Parallel在某些條件下也會(huì)執(zhí)行。不過歸還內(nèi)存可能會(huì)耗費(fèi)一些時(shí)間,所以實(shí)際的實(shí)現(xiàn)會(huì)在歸還內(nèi)存之前會(huì)增加一個(gè)超時(shí)時(shí)間

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

22、安全點(diǎn)檢查
原文標(biāo)題:JVM Anatomy Quark #22: Safepoint Polls

在大部分機(jī)器上停止運(yùn)行的線程實(shí)際上是很簡(jiǎn)單的:向線程發(fā)送一個(gè)信號(hào),強(qiáng)制處理器中斷,停止線程正在執(zhí)行的操作,將控制權(quán)轉(zhuǎn)交給別處。然而,這還不足以讓Java線程在任意位置停止,特別是如果你需要精確的垃圾回收。在這種情況下,你需要知道寄存器和棧中的內(nèi)容,這些內(nèi)容可能是你需要處理的對(duì)象引用。或者如果你想要取消偏向鎖,你需要精確的知道線程的狀態(tài)和獲取的鎖

因此Hotspot實(shí)現(xiàn)了協(xié)作機(jī)制:線程經(jīng)常詢問是否應(yīng)該將控制權(quán)交給VM,在線程生命周期中某些已知的位置,線程的狀態(tài)是已知的。當(dāng)所有線程都在已知的位置停止的時(shí)候,VM 被認(rèn)為是到達(dá)了安全點(diǎn)。檢查安全點(diǎn)請(qǐng)求的代碼片段因此被稱為安全點(diǎn)檢查

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

23、壓縮引用
原文標(biāo)題:JVM Anatomy Quark #23: Compressed References

大部分JVM實(shí)現(xiàn)將Java引用轉(zhuǎn)換為機(jī)器指針,沒有額外的迂回,這簡(jiǎn)化了性能問題,不過通常情況下會(huì)使得引用的表示比機(jī)器指針的寬度小,也就是進(jìn)行壓縮引用,比如你可以使用XX:+UseCompressedOops選項(xiàng),使得在64位系統(tǒng)中對(duì)象指針可以使用32bit的Compressed版本。壓縮方法可以是比特右移,稱為“基于零的壓縮普通對(duì)象指針”,但是基于零的壓縮引用仍然依賴堆內(nèi)存映射在較低地址的假設(shè)。如果不是,我們可以使用非零的堆內(nèi)存起始地址來解碼

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

24、對(duì)象對(duì)齊
原文標(biāo)題:JVM Anatomy Quark #24: Object Alignment

許多硬件實(shí)現(xiàn)要求對(duì)數(shù)據(jù)的訪問是對(duì)齊的,也就是N字節(jié)寬度數(shù)據(jù)的訪問地址總是N的倍數(shù),否則會(huì)直接拒絕操作,產(chǎn)生SIGBUS信號(hào)或者其他硬件異常

在Hotspot中最小的對(duì)象對(duì)齊是8字節(jié),我們可以通過-XX:ObjectAlignmentInBytes選項(xiàng)進(jìn)行調(diào)整,不過會(huì)有正面和負(fù)面的后果

負(fù)面的后果是每個(gè)對(duì)象平均的內(nèi)存空間浪費(fèi)將會(huì)增加,如果啟用壓縮引用,這個(gè)增加會(huì)變得不那么明顯,不過內(nèi)存對(duì)齊會(huì)導(dǎo)致壓縮引用閾值被移動(dòng),因?yàn)樗蕾囈弥杏卸嗌俚臀槐忍厥橇悖@很有趣,總之,利器當(dāng)慎用

翻譯修改摘錄自:

https://shipilev.net/jvm/anat...

文章來源:www.liangsonghua.me

作者介紹:京東資深工程師-梁松華,在穩(wěn)定性保障、敏捷開發(fā)、JAVA高級(jí)、微服務(wù)架構(gòu)方面有深入的理解

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/76072.html

相關(guān)文章

  • 程序員練級(jí)攻略(2018):Java底層知識(shí)

    摘要:最黑科技的玩法就是字節(jié)碼編程,也就是動(dòng)態(tài)修改或是動(dòng)態(tài)生成字節(jié)碼。使用字節(jié)碼編程可以玩出很多高級(jí)玩法,其中最高級(jí)的玩法是在程序運(yùn)行時(shí)進(jìn)行字節(jié)碼修改和代碼注入。 showImg(https://segmentfault.com/img/bVbkqqg?w=1142&h=640);這個(gè)是我訂閱 陳皓老師在極客上的專欄《左耳聽風(fēng)》,我貼出來是為了自己以后方便學(xué)習(xí)和記憶,同時(shí)也分享給你們一起學(xué)習(xí)...

    wean 評(píng)論0 收藏0
  • Cookie, Session, LocalStorage, SessionStorage, Eta

    摘要:理解進(jìn)公園背景這個(gè)公園有一個(gè)總公園總公園里有許多小公園總公園是登錄頁面小公園是域名相同的頁面第一次進(jìn)總公園第一次請(qǐng)求某個(gè)服務(wù)器工作人員檢查你的入園是否符合條件后端查看是否是注冊(cè)以后的用戶通過條件的話工作人員會(huì)給你一張票后端會(huì)給你一個(gè)響應(yīng)頭這 Cookie, Session, LocalStorage, SessionStorage Cookie 理解 進(jìn)公園 背景: 這個(gè)公園有一個(gè)總公...

    imingyu 評(píng)論0 收藏0
  • 解剖okhttp

    摘要:自動(dòng)選擇最好路線并支持自動(dòng)重連擁有自動(dòng)維護(hù)的連接池,減少握手次數(shù),減少請(qǐng)求延遲,共享減少對(duì)服務(wù)器的請(qǐng)求次數(shù)。支持的緩存策略減少重復(fù)的網(wǎng)絡(luò)請(qǐng)求。擁有輕松處理請(qǐng)求與響應(yīng)并自動(dòng)處理數(shù)據(jù)壓縮。支持自簽名的鏈接,配置有效證書即可。 1.OkHttp簡(jiǎn)介: Okhttp與HttpClient、HttpUrlConnection以及Volley類似是一個(gè)網(wǎng)絡(luò)請(qǐng)求框架,支持連接同一地址的鏈接共享同一個(gè)...

    mudiyouyou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<