導航:首頁 > 源碼編譯 > jvm復制回收演算法

jvm復制回收演算法

發布時間:2023-06-01 12:15:00

Ⅰ JVM GC 原理 2:分代式垃圾回收演算法

java 中,大部分對象存在時間很短,小部分對象存活時間長一些,而且存活時纖此陪間長的對象會存在很長時間。按照二八定律的說法:80%的對象占總存活時間的 20%,剩下 20%的對象存活時間卻佔了總存活時間的 80%

根據 java 對象的存活規律,可以將jvm 堆空間劃分為新生代和老年代。新生代存放剛剛被創建的 java 對象(顧名思義嘛, 新生 代),老年代存放已經存活了一段時間的 java 對象(存活時間長了自然就進入了 老年 )。

根據新生代 java 對象的特點:絕大部分都會在很短時間內變成垃圾,被下一次垃圾回收操作所清除。因此可以給新生代訂制一款改進的 復制演算法

將新生代所佔用的堆空間進一步分為 eden 區和 survivors 區,且 s 區分為 s1 區和 s2 區。e 區空間較大,講個 s 區空間較小,每次使用 e 區和 s 區的某一個。例如,先使用 e+s1,當沒有足夠空間時,將 e+s1 中的存活對象放到 s2,然後全部回收 e+s1 的空間,下一個階段使用 e+s2,就這樣依次循環。

在每次新生代垃圾回收時,記錄每個對象的存活時長,當超過存活時長閾值毀蠢(可設定),則該對象將會被放到老年代中。

對於老年代,其中的 java 對象的存活特點是:存活時間長,垃圾率低。因此,在老年代垃圾回收的操作頻率會極大降低,而且每次垃圾回收的數量也不多。由扒帆於這些特點,老年代一般選擇使用 標記-整理演算法

Ⅱ 以下哪些jvm的垃圾回收方式採用的是復制演算法

System.gc是專門回收不用的對象的語法,當然你也可以自己寫函數來finalization()你的程序。一般JVM會根據虛擬內存佔用率來自動調用gc(garbage collector),有時候即便你調用gc如果內存佔用不多回收處理工作也不會調用的,畢竟調用一次也要佔用資

Ⅲ JVM的垃圾演算法有哪幾種

一、垃圾收集器概述

如上圖所示,垃圾回收演算法一共有7個,3個屬於年輕代、三個屬於年老代,G1屬於橫跨年輕代和年老代的演算法。

JVM會從年輕代和年老代各選出一個演算法進行組合,連線表示哪些演算法可以組合使用

二、各個垃圾收集器說明

1、Serial(年輕代)

Ⅳ 你不得不知道的JVM 垃圾回收

一、四種引用方式
1.1 強引用
1.2 軟引用(SoftReference)
1.3 弱引用(WeakReference)
1.4 虛引用(PhantomReference)

二、如何判斷對象是垃圾
2.1 引用計數法
2.2 根可達性分析

三、垃圾回收演算法
3.1 標記-清除(mark-sweep)
3.2 標記-整理(mark-compact)
3.3 標記-復制(mark-)

四、垃圾收集器
4.1 分類及特點簡述
4.1.1 串列
4.1.2 吞吐量優先
4.1.3 響應時間優先
4.2 串列垃圾回收器詳述
4.2.1 Serial
4.2.2 Serial-Old
4.2.3 流程圖
4.3 吞吐量優先垃圾回收器詳述
4.3.1 JVM相關參數
4.3.2 流程圖
4.4、響應時間優先垃圾回收器詳述
4.4.1 JVM相關參數
4.4.2 流程圖
4.3.3 CMS的特點

五、G1垃圾回收器
5.1 相關JVM參數
5.2 特點
5.3 G1新生代垃圾回收
5.4 G1老年代垃圾回收

只有所有 GC Roots對象都不通過【強引用】引用該對象,該對象才可以被回收。

某個對象只要有一處引用關系,該對象的引用次數就加1,如果一個對象的引用次數為0,則說明該對象是垃圾。

優勢:實現簡單,效率較高

弊端:如果有一對對象之間形成了相互引用,但是這兩個對象都已經沒有被其它對象所引用了,正常情況下,這一對對象應該被作為垃圾回收掉,但是因為形成了相互引用導致無法被回收。

通過GC Root對象開始向下尋找,尋找不到的對象即說明沒有被引用,那麼這些沒有被引用的對象被認定為垃圾。

目前,如下對象可以作為GC Root對象:

很好理解,即在GC的放生時候,先對所有對象進行根可達性分析,藉此標記所有的垃圾對象;所有對象標記完畢之後會進行清理操作。

因此,總體來說,就是先標記再清除。

弊端;標記清除之後會產生大量不連續的內存碎片,碎片太多可能會導致程序運行過程中需要分配較大對象時,無法滿足分配要求導致GC操作。

該回收演算法操作過程基本等同於 標記-清除 演算法只不過,第二步有點區別,該種方式會在清除的過程中進行 整理 操作,這是最大的不同。

優勢:最終不會出現若干空間碎片而導致的空間浪費。

弊端:在整理過程中帶來的計算不可小覷。

該種方式與前兩種有較大的區別:

該種方式會將存儲區分成兩個部分,分別為From、To,其中From區域中可能存在著對象,而To區域始終為空,用做下一次接受數據做准備。

分別有兩個指針指向這兩個區域:From-Pointer、To-Pointer,

優點:這種演算法非常適合早生夕死的對象

缺點:始終有一塊內存區域是未使用的,造成空間的浪費。

特點:

特點:

特點:

JVM開關:-XX:+UseSerialGC = Serial + SerialOld

上圖是:CMS垃圾回收器在老年代GC的工作流程圖:

經過上面的文字分析,新生代的Region個數為所有Region個數的5%;這個數值其實是很小的,那麼當新生代Region不夠用的時候,JVM會劃分更多的Region個數給新生代;

當新生代的Region個數佔比所有Region個數超過 60% 時,就會進行一次新生代的垃圾回收。

新生代垃圾回收會造成STW。

具體的垃圾回收演算法同其它幾個新生代垃圾回收器一樣,新生代都使用復制演算法。

老年代垃圾回收觸發機制與參數-XX:InitaingHeapOccupancyPercent有關。

但是需要注意的是:這一次的老年代回收,其實是一次混合垃圾回收,會同時清理新生代、老年代、Humongous。

與新生代回收演算法一致,依然使用復制演算法,但是垃圾回收的過程等同於老年代響應時間優先的CMS方式

流程分為:

Ⅳ JVM(二) GC演算法與分代回收策略

可達性分析演算法是從離散數學中的圖論引入的,jvm把內存中所有的對象之間的引用關系看作一張圖,通過一組名為 GC Root 的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,瞎洞最後通過判斷對象的引用鏈是否可達來決定對象是否可以被回收。如下圖所示:

在java中,有以下幾種對象可以作為GC Root:

從GC Roots集合開始,將內存整個遍歷一次,保留所有可以被GC Roots直接或間接引用到的對象,而剩下的對象都當作垃圾對待並回收,過程分為兩步:

如下圖所示:

將現有的內存空間分為兩塊,每次只使用其中一塊,在垃圾回收時將正在使用的內存中存活對象復制到未被使用的內滑簡存塊中。之後,清除正在使用的內存塊中的所有對信神褲象,交換兩個內存的角色,完成垃圾回收。

需要先從根節點開始對所有可達對象做一次標記,之後,並不是簡單地清理未標記的對象,而是將所有的存活對象壓縮到內存的一段。最後,清理邊界外所有的空間。

JVM提供了相應的GC日誌,在GC執行垃圾回收事件的時候,會有各種相應的log被列印出來,其中新生代與老年代的列印日誌是有區別的。

GC Log分析相關的Java命令參數:

判斷對象是否存活可以通過GC Roots的引用可達性來判斷,JVM中的引用關系有四種,根據引用強度由強到弱,分別是:強引用,軟引用,弱引用,虛引用

Ⅵ jvm垃圾回收有哪些演算法

1.堆的分代和區域
(年輕代)Young Generation(eden、s0、s1 space) Minor GC

(老年代)Old Generation (Tenured space) Major GC|| Full GC

(永久代)Permanent Generation (Permanent space)【方法區(method area)】 Major GC

本地化的String從JDK 7開始就被移除了永久代(Permanent Generation )

JDK 8.HotSpot JVM開始使用本地化的內存存放類的元數據,這個空間叫做元空間(Metaspace)

2.判斷對象是否存活(哪些是垃圾對象)
1.引用計數(ReferenceCounting):對象有引用計數屬性,增加一個引用計數加1,減少一個引用計數減1,計數為0時可回收。(無法解決對象相互循環引用的問題)

2.根搜索(GC Roots Tracing):GCRoot對象作為起始點(根)。如果從根到某個對象是可達的,則該對象稱為「可達對象」(存活對象,不可回收對象)。否則就是不可達對象,可以被回收。

下圖中,對象Object6、Object7、Object8雖然互相引用,但他們的GC Roots是不可到達的,所以它們將會被判定為是可回收的對象

3.垃圾收集演算法
1.標記-清除(Mark-Sweep)演算法:

標記清除演算法分為「標記」和「清除」兩個階段:首先標記出需要回收的對象,標記完成之後統一清除對象。

缺點:

1、標記和清除效率不高;

2、產生大量不連續的內存碎片,導致有大量內存剩餘的情況下,由於,沒有連續的空間來存放較大的對象,從而觸發了另一次垃圾收集動作。

2.復制(Copying)演算法:
將可用內存容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊用完之後,就將還存活的對象復制到另外一塊上面,然後在把已使用過的內存空間一次清理掉。這樣使得每次都是對其中的一塊進行內存回收

Ⅶ JVM垃圾收集機制

JVM垃圾回收機制是java程序員必須要了解的知識,對於程序調優具有很大的幫助(同時也是大廠面試必問題)。

要了解垃圾回收機制,主要從三個方面:

(1)垃圾回收面向的對象是誰?

(2)垃圾回收演算法有哪些?

(3)垃圾收集器有哪些?每個收集器有什麼特點。

接下來一一講解清楚:

一、垃圾回收面向的對象

也就是字面意思, 垃圾 回收嘛,重要的是垃圾,那什麼對象是垃圾呢,簡單來說就是無用的或已死的對象。這樣又引申出來什麼對象是已死的,怎麼判斷對象是否已死?

判斷對象是否已死有兩種演算法和對象引用分類:

(1)引用計數演算法:

也是字面意思,通過給對象添加引用計數器,添加引用+1,反之-1。當引用為0的時候,此時對象就可判斷為無用的。

優點:實現簡單,效率高。

缺點:無法解決循環引用(就是A引用B,B也引用A的情況)的問題。

(2)根搜索演算法(也就是GC Roots):

通過一系列稱為GC Roots的對象,向下搜索,路徑為引用鏈,當某個對象無法向上搜索到GC Roots,也就是成為GC Roots不可達,則為無用對象。

如果一個對象是GC Roots不可達,則需要經過兩次標記才會進行回收,第一次標記的時候,會判斷是否需要執行finalize方法(沒必要執行的情況:沒實現finalize方法或者已經執行過)。如果需要執行finalize方法,則會放入一個回收隊列中,對於回收隊列中的對象,如果執行finalize方法之後,沒法將對象重新跟GC Roots進行關聯,則會進行回收。

很抽象,對吧,來一個明了的解釋?

比如手機壞了(不可達對象),有錢不在乎就直接拿去回收(這就是沒實現finalize方法),如果已經修過但是修不好了(已經執行過finalize方法),就直接拿去回收站回收掉。如果沒修過,就會拿去維修店(回收隊列)進行維修,實在維修不好了(執行了finalize方法,但是無法連上GC Roots),就會拿去回收站回收掉了。

那什麼對象可以成為GC Roots呢?

1>虛擬機棧中的引用對象

2>本地方法棧中Native方法引用的對象

2>方法區靜態屬性引用對象

3>方法區常量引用對象

(3)對象引用分類

1>強引用:例如實例一個對象,就是即使內存不夠用了,打死都不回收的那種。

2>軟引用:有用非必須對象,內存夠,則不進行回收,內存不夠,則回收。例如A借錢給B,當A還有錢的時候,B可以先不還,A沒錢了,B就必須還了。

3>弱引用:非必須對象,只能存活到下一次垃圾回收前。

4>虛引用:幽靈引用,必須跟引用隊列配合使用,目的是回收前收到系統通知。

下面是java的引用類型結構圖:

(1)軟引用示例

內存夠用的情況:

運行結果:

內存不夠用的情況:

運行結果:

(2)弱引用示例結果:

無論如何都會被回收

(3)虛引用示例:

運行結果:

解釋:為什麼2和5的輸出為null呢,如下

3為null是因為還沒有進行gc,所以對象還沒加入到引用隊列中,在gc後就加入到了引用隊列中,所以6有值。

這個虛引用在GC後會將對象放到引用隊列中,所以可以在對象回收後做相應的操作,判斷對象是否在引用隊列中,可以進行後置通知,類似spring aop的後置通知。

二、垃圾回收發生的區域

垃圾回收主要發生在堆內存裡面,而堆內存又細分為 年輕代 老年代 ,默認情況下年輕代和老年代比例為1:2,比如整個堆內存大小為3G,年輕代和老年代分別就是1G和2G,想要更改這個比例需要修改JVM參數-XX:NewRatio,

比如-XX:NewRatio=4,那老年代:年輕代=4:1。而年輕代又分為Eden區,S0(Survivor From)和S1(Survivor To)區,一般Eden:S0:S1=8:1:1,如果想要更改此比例,則修改JVM參數-XX:SurvivorRatio=4,此時就是Eden:S0:S1=4:1:1。

在年輕代發生GC稱為Young GC,老年代發生GC成為Full GC,Young GC比Full GC頻繁。

解析Young GC:

JVM啟動後,第一次GC,就會把Eden區存活的對象移入S0區;第二次GC就是Eden區和S0一起GC,此時會把存活的對象移入S1區,S0清空;第三次GC就是Eden區和S1區進行GC,會把存活的對象移入S0區,如此往復循環15次(默認),就會把存活的對象存入老年區。

類似與如果有三個桶,編號分別為1(1號桶內的沙子是源源不斷的,就像工地上。你們沒去工地搬過磚可能不知道,但是我真的去工地上搬過啊),2,3。1裡面裝有沙子,需要將沙子篩為細沙。首先將桶1內的沙子篩選一遍過後的放置於桶2,第二次篩選就會將桶1和桶2裡面的沙子一起篩,篩完之後放到桶3內,桶2清空。第三次篩選就會將桶1和桶3的沙子一起篩選,曬完放到桶2內,桶3清空。如此往復循環15次,桶2或桶3裡面的沙子就是合格的沙子,就需要放到備用桶內以待使用。

上述中桶1就是Eden區,桶2就是S0區,桶3就是S1區。

三、垃圾回收演算法

三種,分別是復制演算法,標記-清除演算法,標記-整理演算法。

(1)復制演算法。

其會將內存區域分成同樣大小的兩塊,一塊用來使用,另外一塊在GC的時候存放存活的對象,然後將使用的一塊清除。如此循環往復。

適用於新生代。

優點:沒有內存碎片,缺點:只能使用一般的內存。

(2)標記-清除演算法。

使用所有內存區域,在GC的時候會將需要回收的內存區域先進行標記,然後同意回收。

適用於老年代。

缺點:產生大量內存碎片,會直接導致大對象無法分配內存。

(3)標記-整理演算法。

使用所有內存區域,在GC的時候會先將需要回收的內存區域進行標記,然後將存活對象忘一邊移動,最後將清理掉邊界以外的所有內存。

適用於老年代。

四、GC日誌查看

利用JVM參數-XX:+PrintGCDetails就可以在GC的時候列印出GC日誌。

年輕代GC日誌:

老年代GC日誌:

五、垃圾收集器

主要有四類收集器以及七大收集器

四類:

(1)Serial:單線程收集器,阻塞工作線程,它一工作,全部都得停下。

(2)Paralle:Serial的多線程版本,也是阻塞工作線程

(3)CMS(ConcMarkSweep):並行垃圾收集器,可以和工作線程一起工作。

(4)G1:將堆分成大小一致的區域,然後並發的對其進行垃圾回收。

怎麼查看默認的收集器呢?

用JVM參數-XX:+PrintCommandLineFlags,運行之後會輸出如下參數。可以看到,jdk1.8默認是Parallel收集器。

七大收集器:

(1)Serial:串列垃圾收集器,單線程收集器。用於新生代。用JVM參數-XX:+UseSerialGC開啟,開啟後Young區用Serial(底層復制演算法),Old區用Serial Old(Serial的老年代版本,底層是標記整理演算法)。

(2)ParNew:用於新生代,並行收集器。就是Serial的多線程版本。用JVM參數-XX:+UseParNewGC,young:parnew,復制演算法。Old:serialOld,標記整理演算法。-XX:ParallecGCThreads限制線程回收數量,默認跟cpu數目一樣。只是新生代用並行,老年代用串列。

(3)Parallel Scavenge:並行回收收集器。用JVM參數-XX:+UseParallelGC開啟,young:parallel scavenge(底層是復制演算法),old:parallel old(parallel的老年代版本,底層是標記整理),新生代老年代都用並行回收器。

這個收集器有兩個優點:

可控的吞吐量 :就是工作線程工作90%的時間,回收線程工作10%的時間,即是說有90%的吞吐量。

自適應調節策略 :會動態調節參數以獲取最短的停頓時間。

(4)Parallel Old:Parallel Scavenge的老年代版本,用的是標記整理演算法。用JVM參數-XX:+UseParallelOldGC開啟,新生代用Parallel Scavenge,老年代用Parallel Old

(5)CMS(ConcMarkSweep):並發標記清除。 底層是標記清除演算法,所以會產生內存碎片,同時也會耗cpu。 以獲取最短回收停頓時間為目標。-XX:+UseConcMarkSweep,新生代用ParNew,老年代用CMS。CMS必須在堆內存用完之前進行清除,否則會失敗,這時會調用SerialOld後備收集器。

初始標記和重新標記都會停止工作線程,並發標記和並發清除會跟工作線程一起工作。

(6)SerialOld:老年代串列收集器(以後Hotspot虛擬機會直接移除掉)。

(7)G1:G1垃圾收集器,演算法是標記整理,不會產生內存碎片。橫跨新生代老年代。實現盡量高吞吐量,滿足回收停頓時間更短。

G1可以精確控制垃圾收集的停頓時間,用JVM參數-XX:MaxGCPauseMillis=n,n為停頓時間,單位為毫秒。

區域化內存劃片Region,會把整個堆劃分成同樣大小的區域塊(1MB~32MB),最多2048個內存區域塊,所以能支持的最大內存為32*2048=65535MB,約為64G。

上圖是收集前和收集後的對比,有些對象很大,分割之後就是連續的區域,也即是上圖的Humongous。

上述理論可能有點乏味,下圖很清晰明了(某度找的)。

下面來一張整個垃圾回收機制的思維導圖(太大,分成兩部分)。

=======================================================

我是Liusy,一個喜歡健身的程序猿。

歡迎關注【Liusy01】,一起交流Java技術及健身,獲取更多干貨。

Ⅷ 「JVM基礎」——垃圾回收基礎(GC相關)

當內存中的某一個對象無法找到任何引用的時候,這個對象就是一個垃圾對象。

內存泄露(memory leak),是指程序中已動態分配的堆內存由於某種原因程序未將其釋放或無法釋放,造成了內存的浪費,導致程序運行速度減慢甚至程序崩潰等嚴重後果。

STW即stop the world ,指的是JVM進行GC時會暫停所有業務線程。

給每一個對象添加一個引用計數器,t每當有新的引用時,計數器+1,引用結束後計數器-1。任何時刻計數器為0的對象都是不被引用的。

優點:
1. 引用計數演算法在回收垃圾時具有實時性。當一個對象的引用為0的時候會被直接回收,無需等待特定時間就可以釋放內存。
缺點:
1.當出現對象之間循環引用的時候,垃圾回收期無法確定這些對象是否是垃圾,因此無法回收循環引用的對象。(內存泄漏)

從GC Roots節點(起始節點)出發向下搜索,如果沒有任何引用鏈(既GC root不可達),則證明此對象不可用

tracing GC的本質是通過找出所有活對象來把其餘空間認定為「無用」,而不是找出所有死掉的對象並回收它們佔用的空間。GC roots這組引用是tracing GC的起點。要實現語義正確的tracing GC,就必須要能完整枚舉出所有的GC roots,否則就可能會漏掃描應該存活的對象,導致GC錯誤回收了這些被漏掃的活對象。

將需要清除的對象標記出來,清除掉。

標記清除演算法的實現分為兩個階段:

優點:
只對存活的對象進行標記。標記完畢後再掃描整個空間中未被標記的對象進行回收。該演算法不需要進行對象的移動,只需對不存活的對象進行處理,效率高。
缺點
因為直接回收掉了不存活對象,未對內存進行整理,因此會產生內存碎片。內存碎片較多時,當大對象進入內存空間,無法為期分配足夠的內存會提前觸發GC。

將內存一分為二,每次使用一個區域。當觸發gc時,將存活對象復制到另一區域,清除原區域。

它開始時把堆分成 一個對象 面和多個空閑面, 程序從對象面為對象分配空間,當對象滿了,基於ing演算法的垃圾 收集就從根集合(GC Roots)中掃描活動對象,並將每個 活動對象復制到空閑面(使得活動對象所佔的內存之間沒有空閑洞),這樣空閑面變成了對象面,原來的對象面變成了空閑面,程序會在新的對象面中分配內存。

優點

缺點:

標記清除演算法的優化實現,清除垃圾對象的同時壓縮空間。

該演算法標記階段和Mark-Sweep一樣,但是在完成標記之後,它不是直接清理可回收對象,而是將存活對象都向一端移動,然後再清理掉無用對象

優點:
1.因為對空間進行了整理,因此不會產生內存碎片。
缺點
1.因為掃描了兩次,並且在清除的基礎上還增加了整理,因此時間成本高。

Ⅸ Java垃圾回收:GC在什麼時候對什麼做了什麼

1、首先,GC又分為minor GC 和 Full GC(major GC)。Java堆內存分為新生代和老年代,新生代中又分為1個eden區和兩個Survior區域。

2、一般情況下,新創建的對象都會被分配到eden區,這些對象經過一個minor gc後仍然存活將會被移動到Survior區域中,對象在Survior中沒熬過一個Minor GC,年齡就會增加一歲,當他的年齡到達一定程度時,就會被移動到老年代中。

3、當eden區滿時,還存活的對象將被復制到survior區,當一個survior區滿時,此區域的存活對象將被復制到另外一個survior區,當另外一個也滿了的時候,從前一個Survior區復制過來的並且此時還存活的對象,將可能被復制到老年代。因為年輕代中的對象基本都是尺斗乎朝生夕死(80%以上),所以年輕代的垃圾陵悉回收演算法使用的是復制演算法,復制演算法的基本思想是將內存分為兩塊,每次只有其中一塊,當這一塊內存使用完,就將還活著的對象復制到另一塊上面。復制演算法銷賀不會產生內存碎片。

4、在GC開始的時候,對象只會存在於eden區,和名為「From」的Survior區,Survior區「to」是空的。緊接著GCeden區中所有存活的對象都會被復制到「To」,而在from區中,仍存活的對象會根據他們的年齡值來決定去向,年齡到達一定只的對象會被復制到老年代,沒有到達的對象會被復制到to survior中,經過這次gc後,eden區和fromsurvior區已經被清空。這個時候,from和to會交換他們的角色,也就是新的to就是上次GC前的fromMinor GC:從年輕代回收內存。

5、當jvm無法為一個新的對象分配空間時會觸發Minor GC,比如當Eden區滿了。當內存池被填滿的時候,其中的內容全部會被復制,指針會從0開始跟蹤空閑內存。Eden和Survior區不存在內存碎片寫指針總是停留在所使用內存池的頂部。執行minor操作時不會影響到永久代,從永久帶到年輕代的引用被當成GC roots,從年輕代到永久代的引用在標記階段被直接忽略掉(永久代用來存放java的類信息)。如果eden區域中大部分對象被認為是垃圾,永遠也不會復制到Survior區域或者老年代空間。如果正好相反,eden區域大部分新生對象不符合GC條件,Minor GC執行時暫停的線程時間將會長很多。Minor may call "stop the world"。

Ⅹ JVM有哪些垃圾回收演算法

標記-清除,標記-復制,標記-整理

閱讀全文

與jvm復制回收演算法相關的資料

熱點內容
android智能家居藍牙 瀏覽:646
pt螺紋編程 瀏覽:451
手機電音app哪個好 瀏覽:749
checksum命令 瀏覽:637
java創建xml文件 瀏覽:170
算命源碼國際版 瀏覽:283
三菱模塊化編程 瀏覽:718
控制項讀取文件源碼 瀏覽:445
文件夾側面目錄標簽怎麼製作 瀏覽:232
做程序員學什麼 瀏覽:320
pdfeditor教程 瀏覽:880
fortran把文件放入文件夾 瀏覽:709
程序員1年經驗不敢投簡歷 瀏覽:481
如何看電腦的源碼 瀏覽:897
找工作app軟體哪個好 瀏覽:96
信息管理網站源碼 瀏覽:439
小說app哪個好免費 瀏覽:224
域名在線加密 瀏覽:146
軟體編程西安交大 瀏覽:453
是不是串貨的奶粉查不到溯源碼的 瀏覽:825