Java GC 理論

本文聊聊Java 虛擬機的一些概念奸腺,常見GC算法底層過程,圖解血久,并跟蹤日志做分析突照。篇幅有點長,不要抱著一次看完的心態(tài)去看氧吐,多一點耐心讹蘑。

閱讀建議,先看完《深入理解Java 虛擬機》等相關jvm書籍筑舅,了解java 語言特性

GC base

眾所周知座慰,java虛擬沒有使用引用計數(shù),那么翠拣,使用引用計數(shù)和使用GC root 有何差別角骤?好在哪里?

引用計數(shù)

如php心剥,python等語言,容易造成環(huán)形引用背桐,需要特殊的機制來處理优烧。

Garbage Collection Roots:

  • Local variables
  • Active threads
  • Static fields
  • JNI references

JVM GC分為兩步:

標記:Marking is walking through all reachable objects, starting from GC roots and keeping a ledger in native memory about all such objects
清除:Sweeping is making sure the memory addresses occupied by non-reachable objects can be reused by the next allocations.

Fragmenting and Compacting

  • 寫操作需要花費更多的時間來尋找可用的塊
  • 當碎片太多太小,將導致無法為大對象分配內(nèi)存

為了避免內(nèi)存碎片一發(fā)不可收拾链峭,GC的同時JVM也做了內(nèi)存碎片整理畦娄。可以理解為將可達對象全部移到緊挨在一起弊仪,減少碎片熙卡;

Generational Hypothesis

很多對象有以下特點:

  • Most of the objects become unused quickly
  • The ones that do not usually survive for a (very) long time

所以提出分代的概念:

  • Young Generation
  • Old Generation(Tenured)

分代并非沒有缺點:

  • 不同代之間的對象會互相引用,GC時需要計入實際的GC root.
  • JVM由于對 朝生夕死和近乎不死的對象做了優(yōu)化励饵,對于中等壽命的對象表現(xiàn)得很差

Eden

Eden : 對象被創(chuàng)建就默認放Eden驳癌。一般多線程會同時創(chuàng)建多個對象,Eden被切分為更多的Thread Local Allocation Buffer (TLAB for short) 役听。這個buffer允許將大多數(shù)對象分配在線程對應的TLAB里颓鲜,避免了昂貴的線程同步。

  1. Eden的TLAB不夠分配典予,在共享Eden里分配甜滨,
  2. 若不足,則觸發(fā)young GC
  3. youny GC 后還是不夠瘤袖,直接在老年代分配

Survivor Spaces

兩個survivor 有一個是空的
from和to衣摩,eden+from-> to,copy完,from和to的身份要互換

XX:+MaxTenuringThreshold
XX:+MaxTenuringThreshold=0 不復制直接提升到老年代

默認閥值為15

當to裝不下 eden和from所有alive Object的時候?qū)⑦^早觸發(fā)提升捂敌。

Old Generation

由于老年代是預期所有對象傾向于長壽艾扮,只有較少的GC活動既琴,使用移動算法會更劃算。

步驟:

  • Mark reachable objects by setting the marked bit next to all objects accessible through GC roots
  • Delete all unreachable objects
  • Compact the content of old space by copying the live objects contiguously to the beginning of the Old space

PermGen

在Java 8 之前存在栏渺。

永久代呛梆,存放例如classes對象,還有一些內(nèi)置的常量字符串等磕诊。這個區(qū)經(jīng)常導致java.lang.OutOfMemoryError: Permgen space.如沒有明確知道是內(nèi)存泄露填物,解決之道只是簡單把size調(diào)大。

java -XX:MaxPermSize=256m com.mycompany.MyApplication

需要注意的是霎终,jsp 解析會映設為新的java類滞磺,這導致新的class對象產(chǎn)生。還有字節(jié)碼生成cglib等莱褒,是有可能導致PremGen被擠爆的击困。

Metaspace

由于PermGen 的難以使用,Java8 將PermGen 移入Metaspace,并將PermGen 之前一些雜亂的數(shù)據(jù)移到堆上广凸。Metaspace 在本地內(nèi)存分配阅茶,所以不影響java堆的大小。只要進程還有本地內(nèi)存可用就不會觸發(fā)溢出谅海。當Metaspace太大時脸哀,會存入虛擬磁盤,頻繁的磁盤讀寫將導致性能大幅度下降,或者OutOfMemoryError扭吁。

By default, Metaspace size is only limited by the amount of native memory available to the Java process. 但是可以設置大小撞蜂。

java -XX:MaxMetaspaceSize=256m com.mycompany.MyApplication

Minor GC

Collecting garbage from the Young space is called Minor GC.

  1. 當無法為新對象分配空間時將觸發(fā)GC。例如Eden已經(jīng)滿了侥袜。這意味著蝌诡,頻繁的空間申請將導致頻繁Minor-GC

  2. 在整個Minor GC過程中,Tenured(老年代)的概念被忽略枫吧。從老年代到新生代的引用被理解為GC roots,從新生代到老年代的引用在整個標記過程中被忽略浦旱。

  3. Minor GC會觸發(fā)stop-the-world pauses. 當Eden區(qū)的對象大多數(shù)能被識別為垃圾并且從來不copy到Survivor/Old spaces時,這樣的停頓是微不足道的九杂。反之闽寡,大量新生對象不是合格的垃圾,Minor GC將耗費更多的時間尼酿。

tips:
強化作用域概念爷狈,讓對象及時死亡。減少大對象裳擎,長壽對象的使用涎永,短命大對象可以手動賦空指針來提前脫離GC roots;

Minor GC cleans the Young Generation.

Major GC vs Full GC

可以望文生義地理解:

  • Major GC is cleaning the Old space.
  • Full GC is cleaning the entire Heap – both Young and Old spaces.

可這兩者的概念其實是混雜的。首先羡微,多數(shù)的Major GC 是由Minor GC 觸發(fā)的谷饿,所以分割兩者在很多case下是不可能的。另外妈倔,現(xiàn)在很多垃圾收集器有不同的實現(xiàn)博投。G1收集器使用分塊cleaning,嚴格意義上‘cleaning’這個詞也只能是部分正確。這導致我們沒有必要關注到底是MajorGC還是FullGC盯蝴,我們只需要關注到底是停止了所有應用線程還是GC與應用線程同時運行毅哗。

jstat 打印日志,CMS 為垃圾回收器捧挺,對比GC日志會發(fā)現(xiàn)一次CMS 回收jstat顯示兩次FullGC,而實際上是一次CMS的MajorGC執(zhí)行了兩次stop-the-world

CMS 的過程可以理解為:

  1. 初始化標記:stop-the-world + stopping all application threads
  2. 標記和預清理:和應用線程并發(fā)運行
  3. 最終標記:需要stop-the-world
  4. 清理: 和應用線程并發(fā)運行

如果我們只是考慮延遲虑绵,那么jstat的結果足夠我們分析,如果是考慮吞吐量闽烙,jstat將誤導我們翅睛。所以GC日志也是需要看的。

Marking Reachable Objects

垃圾回收步驟可大致分為:

  • 找出依然存活的對象
  • 拋棄其他對象黑竞,也就是死亡的和沒有被使用的
image.png

Garbage Collection Roots:

  • Local variable and input parameters of the currently executing methods
  • Active threads
  • Static field of the loaded classes
  • JNI references

在標記時捕发,有一些方面需要重點關注:

  • 標記的時候需要stop-the-world,當程序stop-the-world,以便于JVM做垃圾回收很魂,叫做save point.
  • stop-the-world的停頓時間與堆的大小和整個堆對象數(shù)量無直接關系扎酷,只與堆存活對象數(shù)量相關.所以提高堆大小并不能直接影響標記時間

Removing Unused Objects

移除無用的對象可以分為三類方法:sweep(清除),compacting(壓縮整理)莫换,copy(復制)。

Sweep

Mark and Sweep algorithms use conceptually the simplest approach to garbage by just ignoring such objects. 類似于機械硬盤骤铃,無用的對象并沒有被擦除拉岁,只是被認為是可分配而已。這種方法實現(xiàn)簡單惰爬。

image.png

缺點:

  • Mark and Sweep 需要維護空閑區(qū)間列表喊暖,以記錄每個空閑區(qū)間的大小和位置,這增加了額外的空間需求撕瞧。
  • 容易出現(xiàn)存在大量小空閑區(qū)間碎片陵叽,卻無法找到合適的大空間來分配大對象,導致拋出OutOfMemoryError

Compact

將所有存活對象移動到內(nèi)存的一端


image.png

缺點:

  • copy對象到內(nèi)存的開頭丛版,維護對象引用巩掺,將增加GC停頓

優(yōu)點:

  • 相對于標記清除,標記整理在分配新對象時通過指針碰撞來分配空間页畦,代價非常之低胖替。
  • 不存在碎片問題,空閑區(qū)域大小是可見的。

Copy

標記復制独令,和Compact類似端朵,都需要對所有對象維護引用


image.png

優(yōu)點:標記和復制過程可以同時進行。
缺點:需要更多的空間來容納存活對象

image.png

實際上只需要關注這四種組合燃箭,其他的要么未實現(xiàn)冲呢,要么不切實際。

  • Serial GC for both the Young and Old generations
  • Parallel GC for both the Young and Old generations
  • Parallel New for Young + Concurrent Mark and Sweep (CMS) for the Old Generation
  • G1, which encompasses collection of both Young and Old generations
Young Tenured JVM options
Serial Serial -XX:+UseSerialGC
Parallel Scavenge Parallel Old -XX:+UseParallelGC -XX:+UseParallelOldGC
Parallel New CMS -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
G1 -XX:+UseG1GC

Serial GC

所有的minor GC都是mark-copy

SerialGC 老年代用mark-sweep-compact招狸,標記整理

java -XX:+UseSerialGC com.mypackages.MyExecutableClass

單線程敬拓,stop-the-world,限制了性能發(fā)揮瓢颅,不適合作為服務器運行恩尾。

minor GC
full GC

Parallel GC

并行GC

老年代使用mark-sweep-compact

 -XX:ParallelGCThreads=NNN  設置并行線程數(shù)
java -XX:+UseParallelGC -XX:+UseParallelOldGC com.mypackages.MyExecutableClass

優(yōu)點:高吞吐量:

  • during collection, all cores are cleaning the garbage in parallel, resulting in shorter pauses
  • between garbage collection cycles neither of the collectors is consuming any resources

弱勢:還是會有延遲,如果是需要低延遲挽懦,這不是好的選擇翰意。

https://plumbr.io/handbook/garbage-collection-algorithms-implementations#serial-gc

為什么full gc會導致年輕代為空?

Concurrent Mark and Sweep

和ParNew搭配

The official name for this collection of garbage collectors is “Mostly Concurrent Mark and Sweep Garbage Collector”.

It uses the parallel stop-the-world mark-copy algorithm in the Young Generation and the mostly concurrent mark-sweep algorithm in the Old Generation.

年輕代:標記復制
老年代:標記清除

對老年代信柿,它不會造成長時間的停頓:

  1. 他沒有使用標記復制冀偶,或整理,而是使用free list來管理空閑的區(qū)域渔嚷,這節(jié)省了復制的時間进鸠。
  2. 它所做的大多數(shù)工作都在標記清除階段,和application并發(fā)運行形病,當然客年,這仍然需要和application競爭cpu資源
設置使用cms
java -XX:+UseConcMarkSweepGC com.mypackages.MyExecutableClass

低延時,可以讓用戶有更好的體驗.因為大多數(shù)時間都存在一部分cpu資源在做gc漠吻,對于吞吐量優(yōu)先的程序量瓜,他的表現(xiàn)不如Parallel GC.

Phase 1: Initial Mark

標記老年代所有和GC roots 或者年輕帶存活對象直接相連的對象,后者至關重要途乃,因為這是分代收集绍傲。

image.png
2015-05-26T16:23:07.321-0200: 64.42: [GC (CMS Initial Mark[1 CMS-initial-mark: 10812086K(11901376K)] 10887844K(12514816K), 0.0001997 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

注:
2015-05-26T16:23:07.321-0200: 64.42: – GC開始的時鐘時間和相對JVM啟動的時間
CMS Initial Mark – 步驟
10812086K – Currently used Old Generation.
(11901376K) – Total available memory in the Old Generation.
10887844K – Currently used heap
(12514816K) – Total available heap
0.0001997 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] – Duration of the phase, measured also in user, system and real time.

Phase 2: Concurrent Mark

從步驟一標記的對象出發(fā),遍歷整個老年代并標記所有存活對象耍共。
并發(fā)烫饼,不需要stw
需要注意的是,并非所有的存活對象都會被標記出來试读,因為標記的同時杠纵,應用的運行會導致引用關系的改變。

圖中钩骇,因為應用運行的關系淡诗,黑色對象移除了一個引用關系
2015-05-26T16:23:07.321-0200: 64.425: [CMS-concurrent-mark-start]
2015-05-26T16:23:07.357-0200: 64.460: [CMS-concurrent-mark1: 035/0.035 secs2] [Times: user=0.07 sys=0.00, real=0.03 secs]3



CMS-concurrent-mark – 在這個階段骇塘,遍歷老年代并標記所有存活對象
035/0.035 secs – 停止時間,顯示經(jīng)過的時間和墻鐘時間(現(xiàn)實世界時間)
[Times: user=0.07 sys=0.00, real=0.03 secs] – 對并發(fā)任務的計時是沒意義的韩容。

Phase 3: Concurrent Preclean.

  • 并發(fā)過程

在第二步進行的同時,一些引用關系會被改變款违。當改變發(fā)生時,JVM會將 導致改變的對象對應的堆區(qū)域(Card)標記為“dirty”(臟)群凶。

image.png

在pre-cleaning 階段插爹,這些臟對象也被考慮在內(nèi),他們的可達對象也會被標記请梢,標記結束后赠尾,card會被清除。

image.png

另外毅弧,一些為Final Remark 過程做的必要準備也將被執(zhí)行

2015-05-26T16:23:07.357-0200: 64.460: [CMS-concurrent-preclean-start]
2015-05-26T16:23:07.373-0200: 64.476: [CMS-concurrent-preclean: 0.016/0.016 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

CMS-concurrent-preclean – Phase of the collection – “Concurrent Preclean” in this occasion – accounting for references being changed during previous marking phase.
0.016/0.016 secs –  elapsed time and wall clock time.

Phase 4: Concurrent Abortable Preclean

并發(fā)可停止的預清理气嫁。不需要stop-the-world

這個過程盡可能把 不需要stop-the-world (Final Remark) 的工作完成。精確測量此階段時間是不可能的够坐,因為它與很多因素有關寸宵,如迭代的次數(shù),過去的墻鐘時間元咙,某些有用的任務被完成梯影。

2015-05-26T16:23:07.373-0200: 64.476: [CMS-concurrent-abortable-preclean-start]
2015-05-26T16:23:08.446-0200: 65.550: [CMS-concurrent-abortable-preclean1: 0.167/1.074 secs2] [Times: user=0.20 sys=0.00, real=1.07 secs]3


0.167/1.074 secs – user time(CPU time)/clock time

需要注意的是,user time 比時鐘時間少得多庶香。

It is interesting to note that the user time reported is a lot smaller than clock time. 
經(jīng)常我們看到真實時間(clock time)少于user time(cpu time)甲棍,意味著有些工作是并行的,因此消耗的時鐘時間小于CPU時間(cpu time:每個cpu消耗時間的總和)赶掖。這里我們有一小部分的任務需要完成素标,然后GC線程做了很多的等待盾致。
事實上链韭,他們在盡可能地避開長時間的stop-the-world,默認情況下幻梯,這種停頓可能長達5s.


這過程將顯著影響最后標記的stw,并且又很多復雜的配置優(yōu)化和失敗模式呈驶。

Phase 5: Final Remark

最后一次stop-the-world.目標是標記老年代所有存活對象拷泽。前面的Concurrent Preclean是并發(fā)的疫鹊,并不能保證趕得上應用程序?qū)σ玫淖兏俣刃湔埃砸淮伪匾膕top-the-world可以結束這種不確定狀態(tài)。

經(jīng)常的拆吆,CMS盡量在年輕代盡量為空的情況下進行聋迎,以避免兩次stop-the-world接踵而至。(響應時間優(yōu)先)

2015-05-26T16:23:08.447-0200: 65.550: [GC (CMS Final Remark) [YG occupancy: 387920 K (613440 K)]65.550: [Rescan (parallel) , 0.0085125 secs]465.559: [weak refs processing, 0.0000243 secs]65.5595: [class unloading, 0.0013120 secs]65.5606: [scrub string table, 0.0001759 secs7][1 CMS-remark: 10812086K(11901376K)8] 11200006K(12514816K) 9, 0.0110730 secs10] [[Times: user=0.06 sys=0.00, real=0.01 secs]11


CMS Final Remark – “Final Remark” in this occasion – 標記所有老年代的對象枣耀,包括在 前面同步標記過程中創(chuàng)建和修改的引用
YG occupancy: 387920 K (613440 K) – 當前年輕代 已用霉晕、總共的容量 
[Rescan (parallel) , 0.0085125 secs] – 重新掃描,在應用停止時并行掃描所有的存活對象,耗時 0.0085125 s牺堰。
weak refs processing, 0.0000243 secs]65.559 – 第一個子過程拄轻,弱引用處理。
class unloading, 0.0013120 secs]65.560 – 第二個子過程伟葫,卸載無用的classes
scrub string table, 0.0001759 secs – 第三個恨搓,最后一個子過程,分別清除 類級別元數(shù)據(jù)和內(nèi)部字符串對應的符號和字符串

10812086K(11901376K) – 此過程結束后筏养,老年代已用和總容量
11200006K(12514816K)  – 結束后斧抱,整個堆,已用渐溶,總容量辉浦。
0.0110730 secs – 過程耗時.
[Times: user=0.06 sys=0.00, real=0.01 secs] – Duration of the pause, measured in user, system and real time categories.

至此,所有無用對象都被標記出來了茎辐。

Phase 6: Concurrent Sweep

刪除未使用的對象并回收宪郊,以備后面使用。

image.png
2015-05-26T16:23:08.458-0200: 65.56: [CMS-concurrent-sweep-start] 2015-05-26T16:23:08.485-0200: 65.588: [CMS-concurrent-sweep1: 0.027/0.027 secs] [[Times: user=0.03 sys=0.00, real=0.03 secs] 

Phase 7: Concurrent Reset

重置內(nèi)部數(shù)據(jù)結構為下次GC做準備荔茬。

優(yōu)點:CMS通過盡可能地將一些工作拆分到并發(fā)線程來減少stop-the-world的 停頓.
缺點:

  • 導致老年代內(nèi)存碎片
  • 在某些情境下废膘,無法預估GC時間,尤其是遇到大的堆空間慕蔚。

G1 – Garbage First

一個關鍵的設計目標:使得GC時間可預測和可配置丐黄。
G1是一個軟實時的垃圾回收器,你可以設置在x時間內(nèi)stop-the-world不超過y孔飒。它會盡量達標灌闺,但不是一定準確的。

G1 定義了一些新的概念:

  1. 堆不再切分為老年代和新生代坏瞄,而是分成很多的heap regions(默認2048)桂对。每個區(qū)域可以是Eden,survivor,old region鸠匀。所有Eden和Survivor的集合就是新生代蕉斜,所有old region的集合就是老年代。
image.png

這避免了一次性收集整個堆缀棍≌耍可以增量式的收集:每一次只收集區(qū)域集合的一個子集。每次暫停爬范,收集所有的年輕代父腕,并收集部分老年代。

image.png
  1. 在整個并發(fā)過程青瀑,他估算每個region里的實時數(shù)據(jù)量璧亮,并據(jù)此導出收集子集:包含更多垃圾的region應該首先被收集萧诫。這也是他名字 garbage-first collection.

java -XX:+UseG1GC com.mypackages.MyExecutableClass

Evacuation Pause: Fully Young

一開始,缺乏并發(fā)過程的相關信息枝嘶,所以以完全年輕的狀態(tài)運行帘饶。當年輕代被填補,應用線程停止,年輕代存活的數(shù)據(jù)被copy到survivor群扶,部分空閑區(qū)域變成survivor尖奔。

copy的過程稱為“Evacuation”(疏散),類似于其他ygc的copy穷当。

0.134: [GC pause (G1 Evacuation Pause) (young), 0.0144119 secs]
    [Parallel Time: 13.9 ms, GC Workers: 8]
        …
    [Code Root Fixup: 0.0 ms]
    [Code Root Purge: 0.0 ms]
    [Clear CT: 0.1 ms]
    [Other: 0.4 ms]
        …
    [Eden: 24.0M(24.0M)->0.0B(13.0M) Survivors: 0.0B->3072.0K Heap: 24.0M(256.0M)->21.9M(256.0M)]
     [Times: user=0.04 sys=0.04, real=0.02 secs] 




0.134: [GC pause (G1 Evacuation Pause) (young), 0.0144119 secs] – G1 停止提茁,只清理年輕代,開始于 JVM 啟動后134ms 馁菜,耗費的墻鐘時間為0.0144s.
[Parallel Time: 13.9 ms, GC Workers: 8] – 耗時 13.9 ms (real time) 茴扁,并行使用 8 個線程
… – 略
[Code Root Fixup: 0.0 ms] – 釋放掉那些用來管理并行活動的數(shù)據(jù)結構,需要經(jīng)常接近于0.這是有序進行的
[Code Root Purge: 0.0 ms] – 清除更多的數(shù)據(jù)結構汪疮,應該很快峭火,不一定幾乎為零。有序智嚷。
[Other: 0.4 ms] – 繁雜的其他任務卖丸,很多也是并行的
… – 略
[Eden: 24.0M(24.0M)->0.0B(13.0M)  – 暫停前后Eden區(qū)的已使用(總容量)
Survivors: 0.0B->3072.0K  – Space used by Survivor regions before and after the pause
Heap: 24.0M(256.0M)->21.9M(256.0M)] – Total heap usage and capacity before and after the pause.
[Times: user=0.04 sys=0.04, real=0.02 secs]  – Duration of the GC event, measured in different categories:
user – 所有GC線程耗費CPU時間的總和
sys – 系統(tǒng)調(diào)用和系統(tǒng)等待所耗費的時間
real – 應用停止的墻鐘時間。

G1 的理論還是沒搞懂盏道,暫時不寫下去了稍浆。

本文參考: garbage-collection-algorithms-implementations

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市猜嘱,隨后出現(xiàn)的幾起案子衅枫,更是在濱河造成了極大的恐慌,老刑警劉巖朗伶,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弦撩,死亡現(xiàn)場離奇詭異,居然都是意外死亡论皆,警方通過查閱死者的電腦和手機益楼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來点晴,“玉大人感凤,你說我怎么就攤上這事【醣牵” “怎么了俊扭?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵队橙,是天一觀的道長坠陈。 經(jīng)常有香客問我萨惑,道長,這世上最難降的妖魔是什么仇矾? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任庸蔼,我火速辦了婚禮,結果婚禮上贮匕,老公的妹妹穿的比我還像新娘姐仅。我一直安慰自己,他們只是感情好刻盐,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布掏膏。 她就那樣靜靜地躺著,像睡著了一般敦锌。 火紅的嫁衣襯著肌膚如雪馒疹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天乙墙,我揣著相機與錄音颖变,去河邊找鬼。 笑死听想,一個胖子當著我的面吹牛腥刹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播汉买,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼衔峰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛙粘?” 一聲冷哼從身側響起朽色,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎组题,沒想到半個月后葫男,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡崔列,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年梢褐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赵讯。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盈咳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出边翼,到底是詐尸還是另有隱情鱼响,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布组底,位于F島的核電站丈积,受9級特大地震影響筐骇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜江滨,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一铛纬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧唬滑,春花似錦告唆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稻艰,卻和暖如春茄螃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背连锯。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工归苍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人运怖。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓拼弃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摇展。 傳聞我的和親對象是個殘疾皇子吻氧,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容

  • JVM架構 當一個程序啟動之前,它的class會被類裝載器裝入方法區(qū)(Permanent區(qū))咏连,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,664評論 0 7
  • 原文閱讀 前言 這段時間懈怠了盯孙,罪過! 最近看到有同事也開始用上了微信公眾號寫博客了祟滴,挺好的~給他們點贊振惰,這博客我...
    碼農(nóng)戲碼閱讀 5,968評論 2 31
  • 轉載blog.csdn.net/ning109314/article/details/10411495/ JVM工...
    forever_smile閱讀 5,366評論 1 56
  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虛擬機(JVM)垃圾回收器提供...
    簡欲明心閱讀 89,493評論 17 311
  • young generation garbage collection 整理 DefNew, ParNew, PS...
    andersonoy閱讀 1,315評論 0 1