關于JVM的垃圾回收GC的一些記錄

目錄

一、JVM內存區域劃分

?二、從一個基本問題開始引入垃圾回收

三、GC作用的區域

三、如何確定一個對象是否可以被當成垃圾進行回收

(1)引用計數法

(2)可達性分析算法

(3)引用的類型

(3.1)強引用(Strong Reference)

(3.2)軟引用(Soft Reference)

(3.3)弱引用(Weak Reference)

(3.4)虛引用(Phantom Reference)

(3.5)終結器引用(Final Reference)

(4)垃圾回收器的大致工作流程

四、垃圾回收算法

(1)標記 - 清除算法(Mark Sweep)

(2)標記 - 整理算法(Mark Compact)

(3)復制算法

五、堆的不同區域(分代垃圾回收)

六、堆的不同區域使用不同的垃圾回收算法

七、垃圾回收器

1. 有哪些垃圾回收器

2. CMS垃圾回收器和G1垃圾回收器

八、其它一些說明

JVM相關參數


一、JVM內存區域劃分

?二、從一個基本問題開始引入垃圾回收

????????從一個基本問題思考,既然要進行垃圾回收,那么可定要從某一個區域(內存區域)進行回收(即,把內存區域中的某些對象當成垃圾,把這些垃圾對象占用的內存區域回收回來,從而釋放內存,避免這個區域的內存被占滿)。

? ? ? ? 通過以上一個基本的問題出發,我們可以明確如下幾個問題:

(1)在哪個區域上進行垃圾回收(換句話說:JVM的哪個區域可以執行垃圾回收這個動作);

(2)在這個可以執行垃圾回收的區域中,如何識別出哪些對象是垃圾;

(3)確定了哪些對象可以被當成垃圾進行回收,那么應該使用什么算法進行回收;

(4)針對這個可以執行垃圾回收的區域,此區域又可以分為哪些不同的小區域,各個小區域應該使用哪種垃圾回收算法;

? ? ? ? 針對以上幾個問題,下面逐一進行說明:

三、GC作用的區域

? ? ? ?JVM(Java虛擬機)的垃圾回收主要是針對堆內存進行的。堆內存是用來存儲對象實例的地方,而垃圾回收的主要任務就是識別并清除不再被任何活躍對象引用的對象,從而釋放它們占用的內存空間。因此,垃圾回收器主要關注的是堆內存中的對象,以確保內存的有效利用和系統性能的提高。

三、如何確定一個對象是否可以被當成垃圾進行回收

? ? ? ? 既然已經知道了,垃圾回收是針對堆內存的,那么如何判斷堆內存中的哪些對象可以被當成垃圾進行回收呢?有如下幾種方法:

(1)引用計數法

????????每個對象都會有一個與之關聯的引用計數器,用來記錄指向該對象的引用數量;當一個對象被引用時,其引用計數加一;當一個對象的引用被釋放時,其引用計數減一。當引用計數為0時,表示沒有任何引用指向該對象,即可被視為垃圾對象,可以被回收。

? ? ? ? 盡管引用計數法簡單直觀,但也存在一些問題,例如無法處理循環引用的情況(如:當兩個或多個對象互相引用導致引用計數不為零)。由于這一缺陷,現代的Java虛擬機一般不再使用引用計數法作為判斷對象可以是否被當成垃圾的依據,而是采用基于可達性分析的算法來判斷對象是否可以被當成垃圾進行回收。

(2)可達性分析算法

? ? ? ? Java虛擬機中的垃圾回收器采用可達性分析算法來探索所有存活的對象。問題來了,如何進行探索呢?

? ? ? ? 是通過掃描堆中的對象,看是否能夠沿著 GC Root 對象為起點的引用鏈找到該對象,找不到,表示可以回收;但是問題又來了,哪些對象可以作為 GC Root對象呢?

? ? ? ? 可以使用 Eclipse(沒錯,就是哪個被IDEA打趴下的Eclipse)提供的一個工具(Memory Analyzer (MAT))進行查看(這個工具需要結合 JDK提供的 jmpa 工具進行使用),MAT分析工具官方下載鏈接:Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation

(3)引用的類型

? ? ? ? 上面提到了<引用>,在Java中,有如下幾種引用類型:

(3.1)強引用(Strong Reference)

????????強引用是最常見的引用類型,在代碼中使用最頻繁。當我們使用new關鍵字創建一個對象時,默認就是強引用。只要強引用存在,垃圾回收器就不會回收被引用的對象。即使內存不足時,系統也會拋出OutOfMemoryError異常而不是回收強引用對象。

? ? ? ? 【只有所有GC Roots 對象都不通過【強引用】引用該對象后,該對象才能被垃圾回收】

(3.2)軟引用(Soft Reference)

????????軟引用是一種相對強引用較弱的引用類型。通過SoftReference類來實現。當內存不足時,Java虛擬機會根據一定的策略來決定是否回收軟引用對象。通常情況下,只有在內存不足且沒有強引用指向該對象時,才會回收軟引用對象。軟引用適用于對內存敏感的緩存等場景。

? ? ? ? 【僅有軟引用引用該對象時,在垃圾回收后,內存仍不足時會再次觸發垃圾回收,回收軟引用對象】

????????【可以配合引用隊列來釋放軟引用自身】

(3.3)弱引用(Weak Reference)

????????弱引用(Weak Reference):弱引用是一種比軟引用更弱的引用類型。通過WeakReference類來實現。當垃圾回收器進行回收時,無論內存是否充足,只要弱引用對象沒有被強引用指向,就會被回收。弱引用常用于實現對象注冊表、緩存等場景。

? ? ? ? 【僅有弱引用引用該對象時,在垃圾回收時,無論內存是否充足,都會回收弱引用對象】

? ? ? ? 【可以配合引用隊列來釋放弱引用自身】

(3.4)虛引用(Phantom Reference)

????????虛引用是最弱的引用類型之一。通過PhantomReference類來實現。虛引用的作用是在對象被回收之前,允許程序員在對象被回收時收到一個系統通知。虛引用無法通過引用訪問對象,而是通過ReferenceQueue來獲取相關通知。虛引用常與引用隊列(ReferenceQueue)一起使用,用于某些特定的清理操作。

? ? ? ? 【必須配合引用隊列使用,主要配合ByteBuffer使用,被引用對象回收時,會將虛引用入隊,由Reference Handler 線程調用虛引用相關方法釋放直接內存

(3.5)終結器引用(Final Reference)

????????終結器引用是一種比較特殊的引用類型。當對象具有終結器(Finalizer)時,它會被分配給一個終結器引用。終結器引用的主要作用是在對象銷毀前,通過執行終結器方法進行資源釋放和清理。然而,終結器的使用已不推薦,因為它們具有不確定性和性能問題,應盡量避免使用。

? ? ? ? 【無需手動編碼,但其內部配合引用隊列使用,在垃圾回收時,終結器引用入隊(被引用對象暫時沒有被回收),再由Finalizer線程通過終結器引用找到被引用對象并調用它的finalize方法,第二次GC時才能回收被引用對象】

(4)垃圾回收器的大致工作流程

(1)根搜索:垃圾回收器會從一組稱為"GC Roots"的起始點開始遍歷,例如虛擬機棧中的引用、靜態變量等。任何能從GC Roots開始遍歷到的對象都被認為是活躍對象,不會被回收;

(2)可達性分析:從GC Roots出發,遍歷堆中的對象圖,標記所有被引用的對象為活躍對象;

(3)清除階段:遍歷整個堆,將未被標記為活躍對象的對象標記為垃圾,并進行回收。

? ? ? ? 注意:JVM使用了不同的垃圾回收算法,例如標記-清除、標記-整理和復制算法等。這些算法的具體實現細節可能會有所不同,但基本的判斷原則都是通過可達性分析來確定對象是否可回收。

????????此外,Java還提供了finalize()方法,允許對象在被回收之前執行特定的清理操作。但是,由于finalize()方法的執行時機不確定且開銷較大,因此在實際應用中,建議使用顯式的資源釋放方式,如使用try-with-resources語句塊來確保及時釋放資源。

四、垃圾回收算法

? ? ? ? 既然確定了哪些對象可以被當作垃圾進行回收,那么應該使用怎樣的方法進行垃圾回收呢?換句話說,使用什么垃圾回收算法呢?

(1)標記 - 清除算法(Mark Sweep)

示意圖:

標記階段(Marking Phase)

????????從根對象(如全局變量和活躍線程的棧和寄存器)開始,通過遍歷對象之間的引用關系,標記所有能夠被訪問到的對象。在這個階段,所有被標記的對象被視為活動對象,而未被標記的對象則被視為垃圾對象。?

清除階段(Sweeping Phase)

????????標記階段之后,系統會對堆中的所有對象進行線性遍歷,清除未被標記的對象,并將它們所占用的內存空間進行釋放。這樣就完成了對垃圾對象的回收工作。

優點:

  • 簡單直觀,能夠有效地回收不再使用的內存對象

缺點:

  • 內存碎片化問題和回收效率問題(由于清除階段釋放了大量的內存空間,留下了不連續的內存碎片,可能會導致內存分配時的碎片化問題)
  • 此外,標記-清除算法在執行過程中會停止整個應用程序(Stop the world, STW),可能會導致較長的停頓時間,影響了應用程序的響應速度。

????????因此,在實際應用中,往往會結合其他垃圾回收算法,如壓縮算法(Compaction)、分代算法(Generational Collection)等,來解決標記-清除算法存在的問題,以提高內存管理的效率和性能。?

(2)標記 - 整理算法(Mark Compact)

示意圖:

標記-整理算法有如下幾個階段:

標記(Mark)

????????從根對象出發,遍歷整個對象圖,標記所有活躍對象。活躍對象是指仍然被引用的對象,而非垃圾對象。

整理(Compact)

????????將所有活躍對象向內存的一端移動,緊湊排列,以便在后續步驟中形成連續的可用內存空間。

清除(Sweep)

????????從堆的另一端開始,將未被標記的對象視為垃圾,將其回收,并釋放相應的內存空間。

更新引用:

????????在整理過程中,由于對象的位置發生了變化,需要更新所有對對象的引用,確保引用指向正確的內存地址。

優點:

????????標記-整理算法的優點是可以大幅減少內存碎片的產生,提高內存的利用率

缺點:

????????它需要進行整理和移動對象的操作,可能會引入較大的停頓時間,影響應用程序的響應性能。因此,該算法通常適用于較小的堆內存或對停頓時間要求較低的場景。

(3)復制算法

示意圖:

復制算法有如下幾個步驟:

  1. 將內存空間分為兩個相等的區域:From區和To區。
  2. 在From區中分配內存并創建對象。
  3. 當From區的內存耗盡時,啟動垃圾回收機制。
  4. 從From區中將存活的對象復制到To區。
  5. 清空From區中的所有對象,并交換From區和To區的角色。

????????復制算法的優點在于簡單高效,它解決了標記-清除算法和標記-整理算法中會產生的內存碎片問題。但是,由于需要將存活對象復制到另一塊區域,因此復制算法會導致內存利用率降低一半(需要雙倍的內存空間),適用于新生代的內存回收,不適合用于老年代的大規模對象回收。

????????因此,在JVM中,通常會將堆內存劃分為新生代老年代,新生代主要使用復制算法來進行垃圾回收,而老年代則會采用其他更適合的算法,例如標記-整理算法或標記-清除算法。

五、堆的不同區域(分代垃圾回收)

????????分代回收算法是JVM的一種垃圾回收算法,基于對象的生命周期,將堆內存分為不同的代(Generation),并對不同代采用適合的垃圾回收算法。通常將堆內存劃分為新生代、老年代和持久代(或元數據區),其中新生代又可以進一步劃分為Eden區、Survivor區1和Survivor區2

????????分代回收算法的主要思想是:大部分對象的生命周期很短,很快就會被回收,而只有少數對象的生命周期很長,需要在堆內存中存活較長時間。因此,我們可以采用不同的垃圾回收算法來針對不同的對象生命周期,以達到更好的性能和效果。

????????在分代回收算法中,新生代通常使用復制算法進行垃圾回收,因為大多數對象的生命周期較短,而老年代則采用標記-整理算法或標記-清除算法,因為老年代中的對象生命周期更長,需要更高效的回收算法。而持久代主要存儲類元數據信息等不會被回收的數據,一般不需要進行垃圾回收。

????????分代回收算法的優點在于根據對象的生命周期采用不同的回收算法,可以更好地平衡垃圾回收的效率和停頓時間(STW),并減少不必要的內存復制和整理操作。但是,分代回收算法需要更多的內存空間來劃分不同的代,而且需要更復雜的垃圾回收機制來管理不同代之間的引用關系,因此在實際應用中需要根據具體情況進行選擇和配置。

以下是學習黑馬視頻-JVM教程截的圖

六、堆的不同區域使用不同的垃圾回收算法

? ? ? ? 通過《五、堆的不同區域(分代垃圾回收)》可知:

  1. 新生代通常使用復制算法進行垃圾回收,因為大多數對象的生命周期較短;
  2. 老年代則采用標記-整理算法或標記-清除算法,因為老年代中的對象生命周期更長,需要更高效的回收算法。
  3. 持久代主要存儲類元數據信息等不會被回收的數據,一般不需要進行垃圾回收。

七、垃圾回收器

Oracle官方文檔:Available Collectors (oracle.com)

1. 有哪些垃圾回收器

?

2. CMS垃圾回收器和G1垃圾回收器

CMS(Concurrent Mark Sweep)垃圾回收器和G1(Garbage-First)垃圾回收器都是Java虛擬機的垃圾回收器,它們在內存管理和垃圾回收策略上有一些區別。

  1. 并發性能:CMS垃圾回收器是一種以最短停頓時間為目標的垃圾回收器。它使用并發標記和并發清理的方式來實現垃圾回收,可以在垃圾回收過程中與應用程序并發執行,減少停頓時間,提高系統的響應能力。而G1垃圾回收器也具有并發標記和并發清理的特性,但相比CMS,G1進一步改進了并發性能,通過將堆內存劃分為多個小塊(Region),并采用增量式的方式進行垃圾回收,可以更好地控制每次垃圾回收的時間。

  2. 內存模型:CMS垃圾回收器使用的是分代回收的思想,將堆內存劃分為年輕代和老年代。年輕代使用復制算法進行垃圾回收,老年代使用標記-清除算法。而G1垃圾回收器則是基于分區(Region)的內存模型,將整個堆內存劃分為多個相等大小的區域,并且不再明確區分年輕代和老年代。G1會根據垃圾回收的情況動態地選擇進行回收的區域。

  3. 碎片整理:CMS垃圾回收器在進行垃圾回收時,不會對整個堆內存進行整理,因此可能會導致堆內存的碎片化問題。而G1垃圾回收器采用了分區的方式,并在垃圾回收過程中進行了部分的碎片整理,可以較好地避免堆內存的碎片化問題。【注意:G1垃圾回收器(1)同時注重吞吐量(Throughput)和低延遲(Low latency),默認的暫停目標是 200 ms;(2)超大堆內存,會將堆劃分為多個大小相等的 Region;(3)整體上是 標記+整理 算法,兩個區域之間是 復制 算法 ;(4)相關JVM參數:< -XX:+UseG1GC >? ?<?-XX:G1HeapRegionSize=size >? <?-XX:MaxGCPauseMillis=time >

  4. 停頓時間:CMS垃圾回收器通過并發的方式來減少垃圾回收的停頓時間,但無法完全避免停頓。而G1垃圾回收器則通過控制每次垃圾回收的時間和并發執行的階段,可以更好地控制全局的垃圾回收時間,并且具有更可預測的停頓時間。

綜上所述,CMS垃圾回收器和G1垃圾回收器都是面向低停頓時間的垃圾回收器,但G1相比CMS在并發性能、內存模型、碎片整理和停頓時間上都有進一步的改進和優化。根據具體的應用場景和需求,可以選擇適合的垃圾回收器來進行內存管理。

????????JDK 1.8默認使用的垃圾回收器是ParallelGC,也稱為Parallel Scavenge收集器。這是一種基于標記-復制算法的垃圾回收器,主要針對年輕代進行垃圾回收。ParallelGC使用多個線程并行地進行垃圾回收操作,可以充分利用多核CPU的優勢,以提高垃圾回收的效率。

????????另外,在JDK 1.8中還引入了G1垃圾回收器,它是一種基于分區(Region)的垃圾回收器,相比于ParallelGC具有更好的并發性能和更可預測的停頓時間。但G1不是默認的垃圾回收器,需要通過特定參數進行配置才能啟用。

????????需要注意的是,JDK 1.8中的垃圾回收器并不是固定的,可以通過虛擬機參數進行配置。在實際應用中,需要根據具體的場景和需求來選擇合適的垃圾回收器。

八、其它一些說明

JVM相關參數

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259659.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259659.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259659.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

同步與互斥

有數據交互的進程之間的關系主要有兩種,同步與互斥.所謂互斥,是指在不同進程之間的若干程序片斷,當某個進程運行其中一個程序片段時,其它進程就不能運行它們之中的任一程序片段,只能等到該進程運行完這個程序片段后才可以運行.所謂同步,是指在不同進程之間的若干程序片斷,它們的…

java 分號 轉義_java – 正則表達式和轉義和未轉義的分隔符

你可以使用正則表達式(?:\\.|[^;\\])*匹配未轉義分號之間的所有文本&#xff1a;List matchList new ArrayList();try {Pattern regex Pattern.compile("(?:\\\\.|[^;\\\\])*");Matcher regexMatcher regex.matcher(subjectString);while (regexMatcher.find())…

OpenCV cv::Mat類

using namespace cv; 1、Mat的聲明&#xff1a; Mat mMat(rows, cols, type); Mat mMat(Size(width,height), type); type指矩陣中元素的類型&#xff0c;可以使CV_8U&#xff08;無符號單字節像素&#xff09;&#xff0c;CV_8S&#xff08;有符號單字節像素&#xff09;&…

ubuntu-E:Encountered a section with no Package: header的解決辦法

ubuntu 11.04 出現了如下錯誤&#xff1a; E:Encountered a section with no Package: header 終端中輸入以下兩條命令&#xff1a; sudo rm /var/lib/apt/lists/* -vfsudo apt-get update 執行完了命令之后&#xff0c;軟件更新器應該會自動要求更新的&#xff0c;更新便是。 …

java new collection_使用Java 8新增的Predicate操作Collection集合

Java 8 起為 Collection 集合新增了一個 removeIf(Predicate filter) 方法&#xff0c;該方法將會批量刪除符合 filter 條件的所有元素。該方法需要一個 Predicate 對象作為參數&#xff0c;Predicate 也是函數式接口&#xff0c;因此可使用 Lambda 表達式作為參數。如下程序示…

codevs1219 騎士遍歷(棋盤DP)

題目描述 Description設有一個n*m的棋盤&#xff08;2≤n≤50&#xff0c;2≤m≤50&#xff09;&#xff0c;如下圖&#xff0c;在棋盤上有一個中國象棋馬。 規定&#xff1a; 1)馬只能走日字 2)馬只能向右跳 問給定起點x1,y1和終點x2,y2&#xff0c;求出馬從x1,y1出發到x2,y2的…

php顯示錯誤

error_reporting(E_ALL);ini_set(display_errors, 1);//將出錯信息輸出到一個文本文件ini_set(error_log, dirname(__FILE__) . /error_log.txt);

java ssh免密登錄_SSH公鑰、私鑰配置(SSH免密碼登錄方式)

1.首先使用想要發起ssh免密訪問的用戶A登錄Linux(簡稱客戶端Linux)2.進入該用戶的家目錄(cd ~)&#xff0c;看是否有.ssh文件夾(linux中以.開頭文件夾是隱藏的&#xff0c;使用ll -a進行查看)&#xff0c;如果沒有則創建(mkdir ~/.ssh)&#xff0c;并修改訪問權限(chmod 700 ~…

最近學到的一點東西

1 rpc 2 socket&#xff0c;工作很多年了&#xff0c;才明白這貨的重要性&#xff0c;不過什么樣的通信方式&#xff0c;最底層的連接得用它 3 sip協議 4調試&#xff0c;一定要確認異常出錯位置&#xff0c;不能亂猜 5 某些詭異的問題&#xff0c;可以依靠在加一層解決&#x…

win8, VS2013 .NET 4.5在哪找svcutil.exe?

我這個糾結呀&#xff0c;公司用win8&#xff0c; .NET 4.5。想做一個很簡單的項目&#xff0c;就是wcf宿主iis&#xff0c;項目根目錄下有aspx文件和svc文件。于是參考了一個博客http://www.cnblogs.com/yjmyzz/archive/2008/08/19/1270961.html&#xff0c;[原創]WCF入門級使…

java tbase_使用Java從firebase獲取數據

我在下面的代碼中遇到了一個問題,該代碼幾乎逐字地從Firebase SDK Java文檔中復制到了工作中.我是一個真正的語言的新手,比如來自PHP和JavaScript的webdev背景的Java.基本上,addListenerForSingleValueEvent沒有觸發以返回數據.我注意到了這一點,因為系統打印輸出沒有觸發,因此…

錯誤內存【讀書筆記】C程序中常見的內存操作有關的典型編程錯誤

題記&#xff1a;寫這篇博客要主是加深自己對錯誤內存的認識和總結實現算法時的一些驗經和訓教&#xff0c;如果有錯誤請指出&#xff0c;萬分感謝。 對C/C程序員來講&#xff0c;內存管理是個不小的挑戰&#xff0c;絕對值得慎之又慎&#xff0c;否則讓由上萬行代碼構成的模塊…

Spring_HelloWord

環境&#xff1a;IntelliJ 14 &#xff1b; jdk1.8 Spring操作步驟 1.新建項目---Spring Batch2.IntelliJ會自動加載jar包3.現在就可以在src目錄下寫Java類文件了4.將相應的類部署在XML配置文件spring-config.xml中 &#xff08;Eclipse需要手動創建&#xff0c;貌似名為bean.x…

java 按鈕組_java中創建一個按鈕組,有10個按鈕,分別寫著0,1,2,,3。。。。9

展開全部用Java創建按鈕組32313133353236313431303231363533e59b9ee7ad9431333332643966的程序如下:import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;public class…

Starling 2D框架簡介

本系列是對Introducing Starling pdf的翻譯&#xff0c;下文是對adobe開發人員中心的一片日志的轉載&#xff0c;地址為http://www.adobe.com/cn/devnet/flashplayer/articles/introducing_Starling.html Starling 是在 Stage3D APIs 基礎上開發的一種 ActionScript 3 2D 框架&…

基本數據結構——棧

棧的特征是后進先出&#xff08;last-in, first-out, LIFO&#xff09;。棧上的插入操作稱為壓入&#xff08;PUSH&#xff09;&#xff0c;刪除操作稱為彈出&#xff08;POP&#xff09;。 下面使用一個數組S[n]來實現一個最多容納n個元素的棧。定義一個屬性指向最新插入的元素…

Android AutoCompleteTextView控件實現類似百度搜索提示,限制輸入數字長度

Android AutoCompleteTextView 控件實現類似被搜索提示&#xff0c;效果如下 1.首先貼出布局代碼 activity_main.xml&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res…

Centos/RHEL上查看主板型號

老是搞忘記&#xff0c;專門做個記錄&#xff1a; [rootmedia ~]# dmidecode | grep "Product Name" Product Name: To be filled by O.E.M.Product Name: B75M-D3V 修改默認語言&#xff1a;[chenshouyongmedia ~]$ cat /etc/sysconfig/i18n LANG"en_US.UTF-8…

java即時聊天系統畢業_(完整版)基于Java即時聊天系統的設計與實現畢業論文設計...

目錄1 前言...................................................................................................................................1.1 課題選題背景...................................................................................................…

杭電 1284 錢幣兌換問題【完全背包求方案總數】

解題思路&#xff1a;因為對于完全背包的狀態轉移方程f[v]max(f[v],f[v-c[i]]w[i])已經記錄了所有背包組成的方案&#xff0c;只不過通常問的是求最大值&#xff0c;現在要求方案總數 即為 f[v]sum(f[v],f[v-c[i]w[i]]), Problem Description在一個國家僅有1分&#xff0c;2分&…