Garbage collection (GC) 是 Java Virtual Machine (JVM) 的必要組成部分,它收集沒有使用的 Java 堆內(nèi)存,以便應(yīng)用程序可以繼續(xù)分配新的對象。GC 的效果和性能對于應(yīng)用程序性能和確定 (determinism) 非常重要。IBM WebSphere Application Server V8 附帶的 IBM JVM(在受支持的平臺上)提供 4 種 GC 策略算法:
-Xgcpolicy:optthruput
-Xgcpolicy:optavgpause
-Xgcpolicy:gencon
-Xgcpolicy:balanced
每種算法都提供不同的性能和決定質(zhì)量。此外,WebSphere Application Server
V8 中的默認策略已從 -Xgcpolicy:optthruput
更改為 -Xgcpolicy:gencon
策略。下面我們逐一檢查這些策略,看看這個默認策略更改對它們有何影響。
不同應(yīng)用程序自然有不同的內(nèi)存使用模式。計算密集型數(shù)字處理工作負載使用 Java 堆 (heap) 的方式不同于面向客戶的高度事務(wù)型接口。要以最佳方式處理這些不同種類的工作負載,則需要使用不同的垃圾收集策略。IBM JVM 支持許多垃圾收集策略,它允許您選擇最適合您的應(yīng)用程序的策略。
最簡單的垃圾收集技術(shù)可能是:持續(xù)分配直到耗盡閑置內(nèi)存,然后停止應(yīng)用程序,處理整個堆。盡管這種技術(shù)可能會生成一個非常有效的垃圾收集器,但這意味著用戶程序必須能容忍收集器帶來的暫停。只關(guān)注總流量的工作負載可能會從這種策略中受益。
optthruput 策略 (-Xgcpolicy:optthruput
) 采用的就是這種策略(參見圖 1)。這個收集器)使用一種平行的 “標記-清掃 (mark-sweep)” 算法。簡言之,這意味著收集器首先逐一訪問可訪問的對象,將它們標記為實時數(shù)據(jù)。然后,第二輪訪問掃除未標記的對象,將未使用的閑置內(nèi)存留作新分配之用。大部分這種工作都可以并行完成,因此收集器可以使用額外的線程(默認情況下使用的最大線程數(shù)為 CPU 的數(shù)量)來加快工作速度,減少應(yīng)用程序的暫停時間。
圖 1. 應(yīng)用程序和收集器 CPU 使用情況:optthruput

“標記-清掃” 算法的問題是可能會導(dǎo)致碎片(fragmentation),如圖 2 所示。盡管可能有大量閑置內(nèi)存,但如果它們只是一些小塊,其間夾雜著活動對象,那么可能沒有哪個碎塊大到足以滿足某個特定分配需求。
這個問題的解決方法是壓縮(compaction)。理論上,壓縮程序會將所有活動對象都移動到堆的一端,留下一塊連續(xù)的閑置空間。這是一項昂貴的操作,因為可能會移動每個活動對象,每個經(jīng)過移動的對象的指針都必須更新為新位置。因此,通常只在萬不得已時才進行壓縮。壓縮也可以并行執(zhí)行,但這會降低活動對象的打包效果,可能會生成幾個較小的閑置空間,而不是一整塊閑置空間。
圖 2. 堆碎片

對于愿意損失部分流量、減少暫停時間的應(yīng)用程序而言,可以選擇另一種策略。optavgpause 策略(-Xgcpolicy:optavgpause
)試圖在停止應(yīng)用程序之前盡可能多完成一些 GC 工作,從而縮短暫停時間(參見圖 3)。這種策略也使用 “標記-清掃-壓縮 (mark-sweep-compact)” 收集器,但大部分標記和清掃工作可以在應(yīng)用程序運行時執(zhí)行。根據(jù)程序的分配速度,系統(tǒng)試圖預(yù)測下次需要執(zhí)行垃圾收集的時間。達到這個閾值時,就會啟動一個并發(fā) GC。當(dāng)應(yīng)用程序線程分配對象時,系統(tǒng)偶爾會要求它們在完成分配工作之前執(zhí)行少量 GC 工作。線程執(zhí)行的分配工作越多,要求它完成的 GC 工作也越多。與此同時,會有一個或多個背景 GC 線程使用閑置周期完成余下的工作。如果已經(jīng)完成所有并發(fā)工作,或者閑置內(nèi)存提前耗盡,則將中止應(yīng)用程序并完成收集工作。這種暫停通常比較短,除非需要進行壓縮。由于壓縮需要移動和更新活動對象,因此不能并發(fā)執(zhí)行。
圖 3. 應(yīng)用程序和收集器 CPU 使用情況:optavgpause

很久以前,人們就注意到,創(chuàng)建的大多數(shù)對象只被使用一小段時間。這是編程技術(shù)和應(yīng)用程序類型所導(dǎo)致的結(jié)果。許多常用 Java 慣用語都會創(chuàng)建一些將迅速棄用的幫助程序 (helper) 對象,比如 StringBuffer/StringBuilder
對象和 Iterator 對象??梢苑峙溥@些對象來完成某個特定任務(wù),任務(wù)完成后就很少會再用到這些對象。在更大的范圍內(nèi),實際上事務(wù)型應(yīng)用程序也常常創(chuàng)建一些 “一次性使用、用完作廢” 的對象組。一旦返回數(shù)據(jù)庫查詢的響應(yīng)之后,就不再需要回復(fù)、中間狀態(tài)和查詢本身。
這種發(fā)現(xiàn)導(dǎo)致了分代(generational)垃圾收集器的開發(fā)。其背后的理念是:將堆分割為多個不同區(qū)域,以不同的速度收集這些區(qū)域。新對象被分配到一個稱為托兒所(nursery)(或新空間)的區(qū)域中。由于這個區(qū)域中的大多數(shù)對象很快都將變?yōu)槔?,所以收集該區(qū)域最有利于恢復(fù)內(nèi)存。如果某個對象可能會存活一段時間,則會將它移動到另一個稱為保留區(qū) (tenure)(或舊空間)的區(qū)域中。這些對象不太可能變?yōu)槔?,因此收集器很少檢查它們。對于適當(dāng)?shù)墓ぷ髫撦d,進行垃圾收集的結(jié)果是:由于檢查的內(nèi)存更少,收集更快更有效;而且,經(jīng)過檢查的對象被回收的比例更高一些。收集更快意味著暫停時間更短,因此應(yīng)用程序響應(yīng)性也更好。
IBM 的 gencon 策略(-Xgcpolicy:gencon
)在上述并發(fā)策略之上提供了一個分代 GC( “gen-”)。保留區(qū)空間如上所述收集,而
托兒所空間使用了一個復(fù)制 (copying) 收集器。這種算法的工作方式是將托兒所區(qū)域進一步細分為分配 (allocate) 和幸存者 (survivor) 空間(參見圖 4)。新對象被放置到分配空間中,直到耗盡其閑置空間。然后,應(yīng)用程序會停止,分配空間中的所有活動對象都將復(fù)制到幸存者空間中。然后這兩個空間交換角色:分配空間變?yōu)樾掖嬲呖臻g,幸存者空間變?yōu)榉峙淇臻g,應(yīng)用程序恢復(fù)運行。如果某個對象在幾輪復(fù)制之后得以幸存,則會將它移動到保留區(qū)空間中。
圖 4. gencon 應(yīng)用

理論上,這意味著托兒所空間的一半(即幸存者空間)在任何時點上都未使用。實際上,預(yù)留為幸存者空間的內(nèi)存量會根據(jù)在每次收集中幸存下來的對象的百分比進行實時調(diào)整。如果大多數(shù)新對象都被收集(這是預(yù)期的情況),那么分配空間和幸存者空間之間的分界線就會傾斜,此時需要增加垃圾收集之前可以分配的數(shù)據(jù)量。
這種風(fēng)格的收集器有一個重大好處:通過在每次收集時移動活動對象,托兒所區(qū)域在每次收集時都被隱式壓縮。這會導(dǎo)致閑置空間塊變得盡可能的大,但也可能會將關(guān)系密切的對象(例如 String
及其 char[]
數(shù)據(jù))移動到臨近的內(nèi)存位置。這有助于改進系統(tǒng)內(nèi)存緩存的性能特征,從而提高應(yīng)用程序本身的性能。
托兒所垃圾收集的成本與幸存的數(shù)據(jù)量有關(guān)(參見圖 5)。由于預(yù)期的情況是多數(shù)對象都將是垃圾,因此一次托兒所收集通常導(dǎo)致很短的暫停。盡管應(yīng)該能夠快速收集多數(shù)對象,但有些對象無法收集。這意味著隨著時間的推移,保留區(qū)區(qū)域中將塞滿了長期存活的對象,最終導(dǎo)致需要對整個堆進行一次垃圾收集。上述并發(fā)收集器使用的大部分技術(shù)在這里仍然適用。保留區(qū)區(qū)域的標記將根據(jù)需要并發(fā)運行,而分配和收集是在托兒所區(qū)域中進行的。在 gencon 策略下,保留區(qū)區(qū)域的清掃不是并發(fā)執(zhí)行的,而是作為保留區(qū)主收集的一部分進行的。
圖 5. 應(yīng)用程序和收集器 CPU 使用情況:gencon

WebSphere Application
Server V8 中添加了一個新的垃圾收集策略。這個策略名為 balanced(-Xgcpolicy:balanced
),它擴展了擁有多個不同的堆區(qū)域這個概念,將堆劃分為大量區(qū)域,每個區(qū)域都可以單獨處理。本系列第 2 部分將詳細介紹基于區(qū)域的垃圾收集的基礎(chǔ)知識,特別是將深入討論 balanced 策略。
要調(diào)優(yōu)任何應(yīng)用程序的堆大小,第一步是使用默認堆設(shè)置運行應(yīng)用程序,這允許您測量開箱即用性能。此時,如果堆閑置空間總是低于 40%,或者 GC 暫停高于總運行時間的 10%,就應(yīng)該考慮增加堆大小。最小堆大小和最大堆大小可以分別通過 -Xms<value>
和 -Xmx<value>
修改。
用于垃圾收集的標記和清掃階段的 GC 暫停時間基于堆上的活動對象的數(shù)量。當(dāng)您增加統(tǒng)一工作負載上的堆大小時,標記和清掃階段將繼續(xù)花費大致相同的時間完成操作。因此,通過增加堆大小,可以增加 GC 暫停之間的間隔,從而為應(yīng)用程序提供更多的執(zhí)行時間。
如果 GC 由于碎片問題而執(zhí)行壓縮,那么增加堆大小可能有助于緩解壓縮導(dǎo)致的長時暫停問題。壓縮階段可能會極大地增加 GC 暫停時間,因此,如果壓縮階段經(jīng)常出現(xiàn),那么調(diào)優(yōu)堆設(shè)置就能改進應(yīng)用程序性能。
使用可變大小堆允許 GC 僅對堆使用應(yīng)用程序必需的 OS 資源。隨著應(yīng)用程序程序堆需求的變化,GC 可以通過擴大和收縮堆做出反應(yīng)。GC 只能收縮從堆末尾開始的連續(xù)內(nèi)存塊,因此收縮堆可能需要進行壓縮。實際的收縮和擴大階段很快就能完成,不會明顯增加 GC 暫停時間。通過將最大堆大小設(shè)置為略大于常規(guī)操作所需的大小,應(yīng)用程序能夠通過擴大堆來處理額外的工作負載。
堆需求不變的應(yīng)用程序可以通過使用固定堆大小改進 GC 暫停時間。
調(diào)優(yōu)分代垃圾收集時,最簡單的方法是將托兒所空間視為非分代垃圾收集使用的 Java 堆區(qū)域之外的新 Java 堆區(qū)域。這樣,非分代垃圾收集使用的 Java 堆就變成了保留區(qū)堆。
這種方法是一種保守方法:預(yù)期的情況是保留區(qū)堆的占用率將由于托兒所空間的引入而降低,但它提供了一個安全的起點,特別是從非分代策略遷移時。當(dāng)可以監(jiān)控全局(完全)收集之后的保留區(qū)堆的占用率時,就可以按照 前面 描述的方法來調(diào)整堆大小:
-Xmn<size>
設(shè)置托兒所區(qū)域的初始和最大大小,有效地設(shè)置-Xmns
和-Xmnx
。-Xmns<size>
將托兒所區(qū)域的初始大小設(shè)置為指定的值。-Xmnx<size>
將托兒所區(qū)域的最大大小設(shè)置為指定的值。
托兒所堆大小應(yīng)該是固定的,因此只需要這些選項中的一個:-Xmn
。因此,您只需理解如何正確設(shè)置托兒所堆大小。
要正確設(shè)置托兒所堆大小,首先需要考慮托兒所收集使用的機制,然后考慮隨之出現(xiàn)的二級特征:
- 托兒所收集的工作方式是將數(shù)據(jù)從分配空間復(fù)制到幸存者空間。復(fù)制數(shù)據(jù)是一個比較昂貴耗時的任務(wù)。因此,托兒所收集所花費的時間由需要復(fù)制的數(shù)據(jù)量決定。這不是說要復(fù)制的對象的數(shù)量與托兒所空間自身的大小沒有影響,而是說與復(fù)制實際數(shù)據(jù)的成本相比,這些因素造成的影響相對較小。因此,托兒所收集所花費的時間與需要復(fù)制的數(shù)據(jù)量成正比。
- 在任何給定的收集中,只有有限和固定的數(shù)據(jù)量是 “實時的”。一旦應(yīng)用程序完成啟動并完全填充其緩存后,托兒所堆中需要復(fù)制的 “實時” 數(shù)據(jù)量就由該時點需要完成的工作量來確定。在處理事務(wù)的系統(tǒng)中,需要復(fù)制的實時數(shù)據(jù)量等于某個實時事務(wù)集。例如,如果您使用支持 50 個并發(fā)事務(wù)發(fā)生的 50 個 WebContainer 線程來配置您的應(yīng)用服務(wù)器,那么實時數(shù)據(jù)量就是與那 50 個事務(wù)關(guān)聯(lián)的數(shù)據(jù)量。
這意味著,托兒所收集所需的時間由收集時發(fā)生的并發(fā)事務(wù)的數(shù)量的關(guān)聯(lián)數(shù)據(jù)的大小決定,而不是由托兒所空間的大小決定。這還意味著,隨著托兒所空間的大小增大,托兒所收集之間的間隔時間會隨之增大,但收集所需的時間不會增加。事實上,隨著托兒所空間增大,垃圾收集所需的總時間會隨之降低。
圖 6 顯示,如果托兒所空間的大小低于事務(wù)集的關(guān)聯(lián)實時數(shù)據(jù)的大小,因此托兒所收集之間的時間間隔低于一個事務(wù),則必須多次復(fù)制這些數(shù)據(jù)。
圖 6. 數(shù)據(jù)復(fù)制的平均次數(shù)與托兒所收集之間的時間間隔

隨著托兒所空間大小和托兒所收集之間的時間間隔增加,需要復(fù)制的數(shù)據(jù)量通常會隨之減少,垃圾收集的開銷也會隨之降低。
IBM 垃圾收集器或 JVM 沒有對托兒所堆大小進行直接限制;事實上,托兒所堆大小有時被設(shè)置為 10 GB 甚至 100 GB。但是,操作系統(tǒng)在 Java 進程使用的虛擬內(nèi)存、進程地址空間以及足夠的物理內(nèi)存(RAM)的可用性方面有一些限制。一個 32 位進程在每個平臺上的操作系統(tǒng)限制如圖 7 所示。
圖 7. 按操作系統(tǒng)列示的 32 位地址空間

對 64 位進程的限制要嚴格得多。由于可尋址內(nèi)存的范圍從數(shù)百到數(shù)十億 GB,可用物理內(nèi)存 (RAM) 的限制變得更加重要。
如上所述,最簡單的方法是將托兒所空間視為一個額外的內(nèi)存空間。但是,托兒所堆和保留區(qū)堆實際上都被分配為單個連續(xù)內(nèi)存段,它們的大小可通過 -Xmx
設(shè)置進行控制。如果只使用 -Xmx
設(shè)置,則 -Xmx
值的 25% 用于最大托兒所堆大小,托兒所堆大小允許在那 25% 之內(nèi)進行伸縮。下面提供了 Java 堆布局,如圖 8 所示。
圖 8. 默認堆布局

但是,您應(yīng)該將托兒所堆大小固定為一個較大的值,以最小化垃圾收集花費的時間,增強保留區(qū)堆,使其根據(jù)占用率重置自身大小,從而提高彈性。因此,首選的 Java 堆布局如圖 9 所示。
圖 9. 推薦的堆布局

要實現(xiàn)這個布局,托兒所空間和保留區(qū)空間的最小和最大堆大小的值應(yīng)該設(shè)置如下:各個托兒所空間大小的最大和最小值都相等,而各個保留區(qū)空間大小的最小和最大值各不相同。
例如,如果您想擁有一個 256MB 的托兒所堆大小,而保留區(qū)堆大小介于 756MB 和 1024MB 之間,則這些值應(yīng)該為:
-Xmns256M
-Xmnx256M
-Xmos756M
-Xmox1024M
由于 WebSphere Application Server V8 中的默認 GC 策略已經(jīng)從 optthruput 變?yōu)?gencon,因此需要調(diào)整以前選擇的調(diào)優(yōu)參數(shù)。主要問題是更改堆大小來補償托兒所空間。以前在 optthruput 策略中,以 1G 堆大?。?-Xmx1G
)運行正常的程序在使用 768M 保留區(qū)空間和 256M 托兒所空間運行時可能會出現(xiàn)問題。前面介紹的技術(shù)將有助于您選擇新的堆參數(shù)。
還有一些不太明顯的情況,gencon 可能會表現(xiàn)出不同的行為。
由于類通常是長期存活的對象,因此可以將它們直接分配到保留區(qū)空間。因此,類卸載只能是保留區(qū)收集的一部分。如果應(yīng)用程序非常依賴短期存活的類加載器,且托兒所收集能夠及時處理其他已分配對象,那么保留區(qū)收集可能不會頻繁發(fā)生。這意味著,類和類加載器的數(shù)量將持續(xù)增長,這可能會增加本機內(nèi)存上的壓力,而且會在需要進行保留區(qū)收集時導(dǎo)致收集時間過長,這是因為有太多的類卸載工作需要完成。
如果出現(xiàn)這個問題,有兩種解決方法。第一種方法是在出現(xiàn)大量類加載器時鼓勵進行額外的保留區(qū)收集。命令行選項 -Xgc:classUnloadingKickoffThreshold=<number>
告知系統(tǒng),每當(dāng)新創(chuàng)建的類加載器達到 <number>
時,就會啟動一次并發(fā)保留區(qū)收集。因此,如果指定 -Xgc:classUnloadingKickoffThreshold=100
,那么托兒所收集會仔細觀察,每當(dāng)自上次保留區(qū)收集以來新創(chuàng)建的類加載器數(shù)量達到 100 時,就會啟動一次并發(fā)保留區(qū)收集。第二種方法是改為使用另一種 GC 策略。
類似的問題可能會出現(xiàn)在引用對象(例如 java.lang.ref.Reference
的子類)和使用 finalize()
方法的對象上。如果這兩種對象存活的時間足夠長,在變得無法訪問之前被移動到保留區(qū)空間中,那么可能會經(jīng)過很長時間以后才會運行保留區(qū)收集,“發(fā)現(xiàn)” 這個對象已經(jīng)死亡。如果這些對象占用著大型或稀有本機資源,就有可能導(dǎo)致出現(xiàn)問題。我們將這種對象戲稱為 “冰山” 對象:表面上它們只占用很小的 Java 堆大小,但下面隱藏著巨大的本機資源,垃圾收集器看不到。就像面對真正的冰山一樣,最好的策略是盡可能遠離它們。即使使用其他 GC 策略,也無法保證能夠探測到可終結(jié)的對象,并及時運行它的終止程序 (finalizer)。如果它們占用稀有資源,盡可能地手動釋放它們可能是最佳策略。
默認策略應(yīng)該能為多數(shù)工作負載提供足夠的性能,但它可能不是某個特殊應(yīng)用程序的理想選擇。
類似 “批作業(yè)” 的應(yīng)用程序初始化狀態(tài)并加載要處理的數(shù)據(jù)。這些對象中的大部分將在作業(yè)期間存活,只有少數(shù)幾個額外對象是在作業(yè)運行時創(chuàng)建的。 這種工作負載適合 optthruput 模式,因為預(yù)期的情況是:在任務(wù)完成之前,幾乎沒有垃圾。另一種類似情況是,如果作業(yè)很快完成或只分配很少的對象,那么只要堆大小適當(dāng),作業(yè)運行就不需要垃圾收集。在上述這些情況下,optthruput 收集器的最小開銷會讓您做出最佳選擇。
相比之下,事務(wù)型應(yīng)用程序不斷創(chuàng)建并啟用對象組。在這個上下文中,術(shù)語 “事務(wù)” 主要使用字面意義(比如數(shù)據(jù)庫更新或電子商務(wù)采購)或者采用更寬泛的意義,比如一項獨立工作。舉例來說,服務(wù)一個 Web 頁可以視為一個事務(wù)??蛻魴C提交一個 URL,服務(wù)器計算頁面內(nèi)容并將其發(fā)送給客戶機。一旦客戶機接收到頁面,服務(wù)器就可以丟棄已計算的數(shù)據(jù)。
為了進一步闡述這個定義,我們來看一個標準用戶界面。用戶單擊 Save 按鈕之后,系統(tǒng)會打開一個文件對話框,以便用戶導(dǎo)航文件系統(tǒng),為文檔選擇一個位置。一旦用戶關(guān)閉對話框,就不再需要所有中間狀態(tài)。實質(zhì)上,有些批作業(yè)甚至也是事務(wù)型的。假設(shè)一個任務(wù)正在為一些大型圖像文件創(chuàng)建縮略圖,那么該作業(yè)看起來似乎是一個大型批作業(yè),但在內(nèi)部,作業(yè)分別處理每個圖像,每個處理都形成一個 “事務(wù)”。對于這類工作負載,gencon 模式應(yīng)該能提供好處。
optavgpause 模式介于二者之間。這種模式適用的應(yīng)用程序的特點是:擁有大量長期存活的數(shù)據(jù),這些數(shù)據(jù)隨著程序運行緩慢更改。對于工作負載而言,這種模式比較少見。通常,長期存活的數(shù)據(jù)要么從不更改,要么頻繁更改。也就是說,如果系統(tǒng)擁有緩慢演變的數(shù)據(jù),且這些數(shù)據(jù)創(chuàng)建的中間對象也不多,那么這種系統(tǒng)就適合使用這個策略。由于前面討論的某種原因而不能在 gencon 策略下有效運行的程序可能會受益于 optavgpause 的并發(fā)性。
本文簡要描述了 WebSphere Application Server V8 中的 Java Virtual Machine 中提供的垃圾收集策略。盡管默認設(shè)置應(yīng)該適用于多數(shù)情況,但是,為了獲得最佳性能,可能需要進行一些調(diào)優(yōu)。通過匹配工作負載類型及其使用的 GC 策略并選擇適當(dāng)?shù)亩褏?shù),應(yīng)該能夠減少垃圾收集對應(yīng)用程序的影響。
本系列第 2 部分將介紹一種基于區(qū)域的新的垃圾收集策略 balanced,該策略旨在在 64 位大型多核系統(tǒng)上部署時提高可伸縮性。下一篇文章會涉及到這種新技術(shù)背后的動機、它提供的性能改進以及關(guān)于調(diào)優(yōu)這個新選項的提示和技巧。
學(xué)習(xí)
- Wikipedia: 垃圾收集定義
-
Java 技術(shù),IBM 風(fēng)格: 垃圾收集策略,第 1 部分
-
Java 技術(shù),IBM 風(fēng)格: 垃圾收集策略,第 2 部分
-
IBM developerWorks WebSphere
獲得產(chǎn)品和技術(shù)
-
下載 IBM SDKs for Java
-
IBM Monitoring and Diagnostic Tools for Java - Health Center
-
IBM Monitoring and Diagnostic Tools for Java - Garbage Collection and Memory Vizualiser
- IBM developerWorks 工具包:下載關(guān)鍵 WebSphere 最新的產(chǎn)品工具包。
討論
- 加入 developerWorks 中文社區(qū),developerWorks 社區(qū)是一個面向全球 IT 專業(yè)人員,可以提供博客、書簽、wiki、群組、聯(lián)系、共享和協(xié)作等社區(qū)功能的專業(yè)社交網(wǎng)絡(luò)社區(qū)。
- 加入 IBM 軟件下載與技術(shù)交流群組,參與在線交流。

Chris Bailey 是位于英國的 Hursley Park Development Lab 的 IBM Java Technology Center 團隊成員。作為 IBM Java 服務(wù)和支持組織的技術(shù)架構(gòu)師,他負責(zé)支持 IBM SDK for Java 用戶交付成功的應(yīng)用程序部署。Chris 還參與收集和評估新需求,交付新調(diào)試功能和工具,改進文檔并提高 IBM SDK for Java 的質(zhì)量。