垃圾回收常見面試題:
如何判斷對(duì)象是否死亡。
簡(jiǎn)單的介紹一下強(qiáng)引用、軟引用、弱引用、虛引用。虛引用與軟引用和弱引用的區(qū)別、使用軟引用能帶來(lái)的好處
如何判斷一個(gè)常量是廢棄常量
如何判斷一個(gè)類是無(wú)用的類
垃圾收集有哪些算法,各自的特點(diǎn)?
HotSpot 為什么要分為新生代和老年代?
常見的垃圾回收器有哪些?
介紹一下 CMS、G1 收集器。
Minor GC?和 Full GC 有什么不同呢?
1.如何判斷對(duì)象可以回收
1.1 引用計(jì)數(shù)法
什么是引用計(jì)數(shù)法
引用計(jì)數(shù)法是指在對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器值就加一;當(dāng)引用失效時(shí),計(jì)數(shù)器值就減一;計(jì)數(shù)器為零的對(duì)象就是可以被回收的。
缺點(diǎn):這個(gè)方法實(shí)現(xiàn)簡(jiǎn)單,效率高,但是目前主流的虛擬機(jī)中并沒有選擇這個(gè)算法來(lái)管理內(nèi)存,其最主要的原因是它很難解決對(duì)象之間循環(huán)引用的問題。例如,當(dāng)二個(gè)對(duì)象相互引用時(shí),并且這二個(gè)對(duì)象也不可能再被訪問,那么這二個(gè)對(duì)象將永遠(yuǎn)存在于內(nèi)存當(dāng)中不會(huì)被回收。
1.2 可達(dá)性分析算法
1.什么是可達(dá)性分析算法
可達(dá)性分析算法就是通過(guò)一系列稱為 “GC Roots” 的對(duì)象作為根節(jié)點(diǎn),然后通過(guò)對(duì)象之間的引用關(guān)系查看對(duì)象是否有引用鏈能夠到達(dá)根節(jié)點(diǎn),如果有就認(rèn)為是可達(dá)的,不可以被回收;如果沒有就認(rèn)為是不可達(dá)的,可以被回收。例如:
下圖中的 Object 6 ~ Object 10 之間雖有引用關(guān)系,但它們到 GC Roots 不可達(dá),因此為需要被回收的對(duì)象。
2.可以作為 GC Roots 的對(duì)象
-
在虛擬機(jī)棧中引用的對(duì)象。也就是棧幀中的局部變量表里引用的對(duì)象,例如當(dāng)前正在運(yùn)行的方法所用到的參數(shù)、局部變量、臨時(shí)變量等。
-
在本地方法棧中JNI(即通常所說(shuō)的 Native 方法)引用的對(duì)象
-
靜態(tài)屬性引用的對(duì)象。例如Java類的引用類型靜態(tài)變量
-
被同步鎖(synchronized關(guān)鍵字)持有的對(duì)象
-
Java虛擬機(jī)內(nèi)部的引用,如基本數(shù)據(jù)類型對(duì)應(yīng)的Class對(duì)象、一些常駐的異常對(duì)象(比如NullPointException、OutOfMemoryError等)、系統(tǒng)類加載器等
-
反映Java虛擬機(jī)內(nèi)部情況的JMXBean、JVMTI中注冊(cè)的回調(diào)、本地代碼緩存等。
除了上述這些固定的 GC Roots 集合以外,根據(jù)用戶所選用的垃圾收集器以及當(dāng)前回收的內(nèi)存區(qū)域不同,還可以有其它對(duì)象臨時(shí)性的加入,共同構(gòu)成完整的GC Roots集合。例如后面會(huì)提到的分代收集和局部回收,如果只針對(duì)Java堆中某一塊區(qū)域發(fā)起垃圾收集(例如只針對(duì)新生代的垃圾收集),而這個(gè)區(qū)域的對(duì)象完全有可能被位于堆中其他區(qū)域的對(duì)象所引用,這時(shí)候就需要將這些關(guān)聯(lián)區(qū)域的對(duì)象一并加入GC Roots集合中。
3.四種引用
下面四種引用的引用強(qiáng)度從上到下依次減弱
強(qiáng)引用:
-
被強(qiáng)引用所引用的對(duì)象無(wú)論什么時(shí)候,都不會(huì)被垃圾回收器所回收。我們平時(shí)創(chuàng)建的對(duì)象一般都是強(qiáng)引用。
創(chuàng)建強(qiáng)引用示例
new User()
軟引用:
-
被軟引用所引用的對(duì)象是一些還有用但非必須的對(duì)象。如果內(nèi)存空間足夠,垃圾回收器就不會(huì)回收它,如果內(nèi)存空間不足了,就會(huì)回收這些對(duì)象的內(nèi)存。只要垃圾回收器沒有回收它,該對(duì)象就可以被程序使用。軟引用可以和一個(gè)引用隊(duì)列聯(lián)合使用。
創(chuàng)建軟引用示例
new SoftReference(new User())
弱引用:
-
被弱引用引用的對(duì)象,在垃圾回收時(shí),無(wú)論內(nèi)存是否充足,都會(huì)被回收。弱引用可以和一個(gè)引用隊(duì)列聯(lián)合使用。JDK 提供了 WeakReference 類來(lái)實(shí)現(xiàn)弱引用。
創(chuàng)建弱引用示例
new WeakReference(new User())
虛引用:
-
被虛引用引用的對(duì)象就和沒有任何引用一樣,在任何時(shí)候都可能被垃圾回收,必須配合引用隊(duì)列使用。JDK 提供了 PhantomReference 類來(lái)實(shí)現(xiàn)虛引用。
創(chuàng)建虛引用示例
new PhantomReference(new User())
Note
和引用隊(duì)列聯(lián)合使用的意思就是如果引用的對(duì)象被垃圾回收,Java 虛擬機(jī)就會(huì)把這個(gè)對(duì)象加入到與之關(guān)聯(lián)的引用隊(duì)列中。
引用隊(duì)列是JVM為我們提供的一種保障,如果后期想對(duì)被回收的對(duì)象進(jìn)行處理,就可以從引用隊(duì)列中取出來(lái)進(jìn)行使用。
一個(gè)對(duì)象的引用通常是存儲(chǔ)在一個(gè)變量中的,這個(gè)變量可以是類的成員屬性、成員方法的參數(shù)或返回值,也可以是普通方法中的局部變量等
2.垃圾回收算法
2.1 分代收集
1.分代收集理論
當(dāng)前商業(yè)虛擬機(jī)的垃圾收集器,大多數(shù)都遵循了分代收集的理論進(jìn)行設(shè)計(jì),分代收集實(shí)際建立在二個(gè)分代假說(shuō)之上:
-
弱分代假說(shuō):絕大多數(shù)對(duì)象是朝生夕滅的
-
強(qiáng)分代假說(shuō):熬過(guò)越多次垃圾收集過(guò)程的對(duì)象就越難以消亡
????????這二個(gè)分代假說(shuō)奠定了多款常用的垃圾收集器的一致的設(shè)計(jì)原則:收集器應(yīng)該將Java堆劃分出不同的區(qū)域,然后將回收對(duì)象依據(jù)其年齡(年齡即對(duì)象熬過(guò)垃圾收集過(guò)程的次數(shù))分配到不同的區(qū)域之中存儲(chǔ)。顯而易見,如果一個(gè)區(qū)域中大多數(shù)對(duì)象都是朝生夕滅,難以熬過(guò)垃圾收集過(guò)程的話,那么把它們集中放在一起,每次回收時(shí)只關(guān)注如何保留少量存活而不是去標(biāo)記那些大量將要被回收的對(duì)象,就能以較低代價(jià)回收到大量的空間;如果剩下的都是難以消亡的對(duì)象,那把它們集中放在一塊,虛擬機(jī)便可以使用較低的頻率來(lái)回收這個(gè)區(qū)域。
? ? ? ? 把分代收集理論放到現(xiàn)在的商用Java虛擬機(jī)里,設(shè)計(jì)者一般至少會(huì)把Java堆劃分為新生代和老年代二個(gè)區(qū)域。顧名思義,新生代中,每次垃圾回收都有大批對(duì)象死去,而每次回收后存活的少量對(duì)象,將會(huì)逐步晉升到老年代中存放。針對(duì)新生代或老年代或整個(gè)堆的收集則有如下不同的名詞:
部分收集
-
新生代收集(Minor GC/Young GC):指目標(biāo)只是新生代的垃圾收集
-
老年代收集(Major GC/Old GC):指目標(biāo)只是老年代的收集。目前只有CMS收集器會(huì)有單獨(dú)收集老年代的行為。
-
混合收集:指目標(biāo)是收集整個(gè)新生代以及部分老年代的垃圾收集。目前只有G1收集器會(huì)有這種行為。
整堆收集(Full GC):收集整個(gè)Java堆和方法區(qū)的垃圾收集
注意
1.對(duì)象之間可能會(huì)存在跨代引用。例如,新生代中的對(duì)象有可能被老年代中的對(duì)象所引用,具體解決方法見<<深入理解Java虛擬機(jī)>>
2.在HotSpot中,新生代內(nèi)存不足,會(huì)觸發(fā)Minor GC,使用新生代垃圾回收器完成垃圾回收;老年代內(nèi)存不足,會(huì)觸發(fā)Full GC,使用新生代垃圾回收器完成新生代的垃圾回收,使用老年代垃圾回收器完成老年代的垃圾回收
2.HotSpot 中的分代垃圾回收
HotSpot虛擬機(jī)中,堆內(nèi)存分為新生代、老年代二大區(qū)域,大多數(shù)對(duì)象創(chuàng)建時(shí)都會(huì)被分配在新生代。
-
新生代空間不足時(shí),會(huì)觸發(fā) minor gc,垃圾對(duì)象會(huì)被清理,存活的對(duì)象年齡加 1,并且 Eden 區(qū)和其中一個(gè) Survivor 區(qū)的存活對(duì)象會(huì)被復(fù)制到另外一個(gè)空 Survivor 區(qū)。
-
當(dāng)老年代空間不足,一般會(huì)觸發(fā) full gc。
3.新生代的對(duì)象什么時(shí)候進(jìn)入老年代
-
對(duì)象年齡超過(guò)閾值的進(jìn)入老年代
-
大對(duì)象直接進(jìn)入老年代
-
老年代擔(dān)保:在?Minor GC 之后,新生代存活的對(duì)象占用的空間大于?Survivor 區(qū)的空間大小時(shí),那么多出來(lái)的對(duì)象會(huì)提前進(jìn)入老年代,剩下的對(duì)象會(huì)進(jìn)入 Survivor 區(qū)。
新生代使用的是復(fù)制算法,為了內(nèi)存利用率,只使用其中一個(gè) Survivor 空間來(lái)做輪換備份,因此如果大量對(duì)象在 Minor GC 后仍然存活,導(dǎo)致 Survivor 空間不夠用,就會(huì)通過(guò)分配擔(dān)保機(jī)制,將多出來(lái)的對(duì)象提前轉(zhuǎn)到老年代,此時(shí)如果老年代的可用內(nèi)存小于該對(duì)象的大小,就會(huì)觸發(fā) Full GC。
2.2 標(biāo)記清除算法
什么是標(biāo)記清除
首先標(biāo)記出存活的對(duì)象,然后統(tǒng)一回收所有未被標(biāo)記的對(duì)象。
優(yōu)點(diǎn):
-
回收速度比較快
缺點(diǎn):
-
標(biāo)記清除后會(huì)產(chǎn)生內(nèi)存碎片
2.3 標(biāo)記整理算法
什么是標(biāo)記整理算法
首先標(biāo)記出所有存活的對(duì)象,然后讓所有存活的對(duì)象向內(nèi)存空間一端移動(dòng),最后把邊界以外的內(nèi)存全部清理掉。
優(yōu)點(diǎn):不會(huì)產(chǎn)生內(nèi)存碎片
缺點(diǎn):整理這個(gè)階段的效率比較低
2.4 標(biāo)記復(fù)制算法
什么是標(biāo)記復(fù)制算法
它將可用內(nèi)存劃分為大小相等的二塊,只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還活著的對(duì)象復(fù)制到另外一塊上面,然后再把使用過(guò)的這塊內(nèi)存一次性清理掉。
優(yōu)點(diǎn)
不會(huì)有內(nèi)存碎片
缺點(diǎn)
需要占用雙倍內(nèi)存空間
????????現(xiàn)在的商用Java虛擬機(jī)優(yōu)先采用了這種收集算法去回收新生代。但是,IBM曾有一項(xiàng)研究對(duì)新生代的朝生夕死的特點(diǎn)做了一個(gè)更量化的詮釋:新生代中的對(duì)象有98%熬不過(guò)第一輪收集。因此,并不需要1:1的比例劃分新生代的內(nèi)存空間
2.5 JVM的相關(guān)參數(shù)
3.垃圾回收器
3.1 垃圾回收器概述
什么是垃圾回收器
????????垃圾收集算法是內(nèi)存回收的方法論,而垃圾回收器是內(nèi)存回收的實(shí)踐者?!禞ava虛擬機(jī)規(guī)范》中對(duì)垃圾收集器如何實(shí)現(xiàn)并沒有做出任何規(guī)定,因此不同廠商、不同版本的虛擬機(jī)所包含的垃圾回收器都可能會(huì)有很大差別,不同的虛擬機(jī)一般也會(huì)提供各種參數(shù)供用戶根據(jù)自己的應(yīng)用特點(diǎn)和要求組合出各個(gè)內(nèi)存分代所使用的收集器。
垃圾回收器的分類
1. 串行
- 單線程
- 堆內(nèi)存較小,適合個(gè)人電腦
2. 吞吐量?jī)?yōu)先
- 多線程
- 堆內(nèi)存較大,多核 cpu
- 讓單位時(shí)間內(nèi),STW 的時(shí)間最短,垃圾回收時(shí)間占比最低,這樣就稱吞吐量高
3. 響應(yīng)時(shí)間優(yōu)先
- 多線程
- 堆內(nèi)存較大,多核 cpu 盡可能讓單次 STW 的時(shí)間最短
不同垃圾回收器的組合
????????上圖展示了七種作用于不同分代的垃圾回收器,如果二個(gè)回收器之間存在連線,這說(shuō)明它們可以搭配使用,但這個(gè)關(guān)系不是一成不變的,在JDK的一些版本中,某些組合已經(jīng)被廢棄了。
? ? ? ? 直到目前還沒有最好的垃圾回收器,跟更加不存在萬(wàn)能的垃圾回收器,我們應(yīng)選擇對(duì)具體的應(yīng)用最合適的垃圾回收器。
3.2?Serial 垃圾回收器
Serial 垃圾回收器是一個(gè)單線程垃圾回收器,它在進(jìn)行垃圾回收的時(shí)候必須暫停其它所有線程( "Stop The World" ),直到它回收結(jié)束。采用的標(biāo)記復(fù)制算法。
優(yōu)點(diǎn):簡(jiǎn)單而高效、沒有線程交互的開銷。
缺點(diǎn):Stop The World 時(shí)會(huì)給用戶帶來(lái)非常不好的體驗(yàn)
上面這個(gè)圖中新生代采用的Serial垃圾回收器,老年代采用的是Serial Old垃圾回收器,分別使用了不同的垃圾回收算法。后面的圖同理。
3.3?ParNew 垃圾回收器
ParNew 垃圾回收器其實(shí)就是 Serial 垃圾回收器的多線程版本,除了使用多線程進(jìn)行垃圾回收外,其余行為和 Serial 垃圾回收器完全一樣。新生代采用標(biāo)記-復(fù)制算法。
3.4?Parallel Scavenge 垃圾回收器
Parallel Scavenge 垃圾回收器的關(guān)注點(diǎn)是吞吐量(高效率的利用 CPU)。所謂吞吐量就是 CPU 中用于運(yùn)行用戶代碼的時(shí)間與 CPU 總執(zhí)行時(shí)間的比值。采用的是標(biāo)記-復(fù)制算法。 Parallel Scavenge 收集器提供了很多參數(shù)供用戶找到最合適的停頓時(shí)間或最大吞吐量,是 JDK1.8 默認(rèn)的收集器。
Note:如果對(duì)于收集器運(yùn)作不太了解,手工優(yōu)化存在困難的時(shí)候,使用 Parallel Scavenge 收集器配合自適應(yīng)調(diào)節(jié)策略,把內(nèi)存管理優(yōu)化交給虛擬機(jī)去完成也是一個(gè)不錯(cuò)的選擇。
3.5?Serial Old 垃圾回收器
Serial 垃圾回收器的老年代版本,它同樣是一個(gè)單線程收集器。主要有兩大用途:一種用途是在 JDK1.5 及之前的版本中與 Parallel Scavenge 收集器搭配使用,另一種用途是作為 CMS 收集器的后備方案。
3.6?Parallel Old 垃圾回收器
Parallel Scavenge 垃圾回收器的老年代版本。使用多線程和“標(biāo)記-整理”算法。在注重吞吐量以及 CPU 資源的場(chǎng)合,都可以優(yōu)先考慮 Parallel Scavenge 收集器和 Parallel Old 收集器。
3.7 CMS 垃圾回收器
CMS(Concurrent Mark Sweep)垃圾回收器的目標(biāo)是用最短的停頓時(shí)間進(jìn)行垃圾回收,實(shí)現(xiàn)了讓垃圾回收線程與用戶線程同時(shí)工作。非常適合在注重用戶體驗(yàn)的應(yīng)用上使用。采用的是標(biāo)記清除算法。在老年代上工作。
CMS 收集器是一種實(shí)現(xiàn)了“標(biāo)記-清除”算法的收集器,它的工作過(guò)程相比于前面幾種垃圾收集器來(lái)說(shuō)更加復(fù)雜一些。整個(gè)過(guò)程分為四個(gè)步驟:
-
初始標(biāo)記: 暫停所有的其他線程,并記錄下直接與 root 相連的對(duì)象,速度很快 ;
-
并發(fā)標(biāo)記: 同時(shí)開啟 GC 和用戶線程,用一個(gè)閉包結(jié)構(gòu)去記錄可達(dá)對(duì)象。但在這個(gè)階段結(jié)束,這個(gè)閉包結(jié)構(gòu)并不能保證包含當(dāng)前所有的可達(dá)對(duì)象。因?yàn)橛脩艟€程可能會(huì)不斷的更新引用域,所以 GC 線程無(wú)法保證可達(dá)性分析的實(shí)時(shí)性。所以這個(gè)算法里會(huì)跟蹤記錄這些發(fā)生引用更新的地方。
-
重新標(biāo)記: 重新標(biāo)記階段就是為了修正并發(fā)標(biāo)記期間因?yàn)橛脩舫绦蚶^續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,這個(gè)階段的停頓時(shí)間一般會(huì)比初始標(biāo)記階段的時(shí)間稍長(zhǎng),遠(yuǎn)遠(yuǎn)比并發(fā)標(biāo)記階段時(shí)間短
-
并發(fā)清除: 開啟用戶線程,同時(shí) GC 線程開始對(duì)未標(biāo)記的區(qū)域做清掃。
優(yōu)點(diǎn):并發(fā)收集、低停頓。
缺點(diǎn):
-
對(duì) CPU 資源敏感;
-
無(wú)法處理浮動(dòng)垃圾;
-
它使用的回收算法-“標(biāo)記-清除”算法會(huì)導(dǎo)致收集結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生。
3.8?G1 垃圾回收器
G1 (Garbage-First)垃圾回收器主要面向有多顆處理器和大容量?jī)?nèi)存的服務(wù)器。在進(jìn)行垃圾回收時(shí),既有很短的停頓時(shí)間,又具備很高的吞吐量。同時(shí)工作在新生代和老年代,被視為 JDK1.7 中 HotSpot 虛擬機(jī)的一個(gè)重要進(jìn)化特征。它具備以下特點(diǎn):
-
并行與并發(fā):G1 能充分利用 CPU、多核環(huán)境下的硬件優(yōu)勢(shì),使用多個(gè) CPU(CPU 或者 CPU 核心)來(lái)縮短 Stop-The-World 停頓時(shí)間。部分其他收集器原本需要停頓 Java 線程執(zhí)行的 GC 動(dòng)作,G1 收集器仍然可以通過(guò)并發(fā)的方式讓 java 程序繼續(xù)執(zhí)行。
-
分代收集:雖然 G1 可以不需要其他收集器配合就能獨(dú)立管理整個(gè) GC 堆,但是還是保留了分代的概念。
-
空間整合:與 CMS 的“標(biāo)記-清除”算法不同,G1 從整體來(lái)看是基于“標(biāo)記-整理”算法實(shí)現(xiàn)的收集器;從局部上來(lái)看是基于“標(biāo)記-復(fù)制”算法實(shí)現(xiàn)的。
-
可預(yù)測(cè)的停頓:這是 G1 相對(duì)于 CMS 的另一個(gè)大優(yōu)勢(shì),降低停頓時(shí)間是 G1 和 CMS 共同的關(guān)注點(diǎn),但 G1 除了追求低停頓外,還能建立可預(yù)測(cè)的停頓時(shí)間模型,能讓使用者明確指定在一個(gè)長(zhǎng)度為 M 毫秒的時(shí)間片段內(nèi),消耗在垃圾收集上的時(shí)間不得超過(guò) N 毫秒。
G1 收集器的運(yùn)作大致分為以下幾個(gè)步驟:
-
初始標(biāo)記
-
并發(fā)標(biāo)記
-
最終標(biāo)記
-
篩選回收
G1 收集器在后臺(tái)維護(hù)了一個(gè)優(yōu)先列表,每次根據(jù)允許的收集時(shí)間,優(yōu)先選擇回收價(jià)值最大的 Region。這種使用 Region 劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式,保證了 G1 收集器在有限時(shí)間內(nèi)可以盡可能高的收集效率(把內(nèi)存化整為零)。
從 JDK9 開始,G1 垃圾收集器成為了默認(rèn)的垃圾收集器。
4.垃圾回收器常見面試題
1.如何判斷一個(gè)常量是廢棄常量?
如果一個(gè)常量沒有被任何變量引用的話,那這個(gè)常量就是廢棄常量,在垃圾回收時(shí)可以被回收掉。例如:在字符串常量池中存在字符串 "abc",如果當(dāng)前沒有任何 String 類型的變量引用該字符串常量的話,就說(shuō)明常量 "abc" 就是廢棄常量,如果這時(shí)發(fā)生內(nèi)存回收的話而且有必要的話,"abc" 就會(huì)被系統(tǒng)清理出常量池了。
2.如何判斷一個(gè)類是無(wú)用的類?
方法區(qū)主要回收的是無(wú)用的類,那么如何判斷一個(gè)類是無(wú)用的類呢,類需要同時(shí)滿足?3 個(gè)條件才能算是 “無(wú)用的類”,才可以被被回收掉:
-
該類所有的實(shí)例都已經(jīng)被回收,也就是 Java 堆中不存在該類的任何實(shí)例。
-
該類對(duì)應(yīng)的類對(duì)象沒有在任何地方被引用。
-
加載該類的 ClassLoader 已經(jīng)被回收。
Note:虛擬機(jī)可以對(duì)滿足上述 3 個(gè)條件的無(wú)用類進(jìn)行回收,這里說(shuō)的僅僅是“可以”,而并不是和對(duì)象一樣不使用了就會(huì)必然被回收文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-623981.html
3.HotSpot 為什么要分為新生代和老年代?
因?yàn)?Java 中對(duì)象的存活時(shí)間有長(zhǎng)有短,通過(guò)將 Java 堆劃分為新生代和老年代,在新生代存儲(chǔ)存活時(shí)間短的對(duì)象,在老年代中存儲(chǔ)存活時(shí)間長(zhǎng)的對(duì)象,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)選擇合適的垃圾回收器。在新生代中,每次垃圾回收都會(huì)有大量對(duì)象死去,所以可以選擇”標(biāo)記-復(fù)制“算法。而老年代的對(duì)象存活幾率是比較高的,而且沒有額外的空間對(duì)它進(jìn)行分配擔(dān)保,所以必須選擇“標(biāo)記-清除”或“標(biāo)記-整理”算法進(jìn)行垃圾回收。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-623981.html
到了這里,關(guān)于JVM之垃圾回收器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!