日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Java內(nèi)存泄露的理解與解決

系統(tǒng) 2051 0

轉(zhuǎn)載自 ---- http://henryyang.iteye.com/blog/1188328


Java 內(nèi)存管理機(jī)制

C++ 語言中,如果需要?jiǎng)討B(tài)分配一塊內(nèi)存,程序員需要負(fù)責(zé)這塊內(nèi)存的整個(gè)生命周期。從申請(qǐng)分配、到使用、再到最后的釋放。這樣的過程非常靈活,但是卻十分繁瑣,程序員很容易由于疏忽而忘記釋放內(nèi)存,從而導(dǎo)致內(nèi)存的泄露。 Java 語言對(duì)內(nèi)存管理做了自己的優(yōu)化,這就是垃圾回收機(jī)制。 Java 的幾乎所有內(nèi)存對(duì)象都是在堆內(nèi)存上分配(基本數(shù)據(jù)類型除外),然后由 GC garbage ?collection )負(fù)責(zé)自動(dòng)回收不再使用的內(nèi)存。

????上面是 Java 內(nèi)存管理機(jī)制的基本情況。但是如果僅僅理解到這里,我們?cè)趯?shí)際的項(xiàng)目開發(fā)中仍然會(huì)遇到內(nèi)存泄漏的問題。也許有人表示懷疑,既然 Java 的垃圾回收機(jī)制能夠自動(dòng)的回收內(nèi)存,怎么還會(huì)出現(xiàn)內(nèi)存泄漏的情況呢?這個(gè)問題,我們需要知道 GC 在什么時(shí)候回收內(nèi)存對(duì)象,什么樣的內(nèi)存對(duì)象會(huì)被 GC 認(rèn)為是“不再使用”的。

????Java 中對(duì)內(nèi)存對(duì)象的訪問,使用的是引用的方式。在 Java 代碼中我們維護(hù)一個(gè)內(nèi)存對(duì)象的引用變量,通過這個(gè)引用變量的值,我們可以訪問到對(duì)應(yīng)的內(nèi)存地址中的內(nèi)存對(duì)象空間。在 Java 程序中,這個(gè)引用變量本身既可以存放堆內(nèi)存中,又可以放在代碼棧的內(nèi)存中(與基本數(shù)據(jù)類型相同)。 GC 線程會(huì)從代碼棧中的引用變量開始跟蹤,從而判定哪些內(nèi)存是正在使用的。如果 GC 線程通過這種方式,無法跟蹤到某一塊堆內(nèi)存,那么 GC 就認(rèn)為這塊內(nèi)存將不再使用了(因?yàn)榇a中已經(jīng)無法訪問這塊內(nèi)存了)。

?

?

????通過這種有向圖的內(nèi)存管理方式,當(dāng)一個(gè)內(nèi)存對(duì)象失去了所有的引用之后, GC 就可以將其回收。反過來說,如果這個(gè)對(duì)象還存在引用,那么它將不會(huì)被 GC 回收,哪怕是 Java 虛擬機(jī)拋出 OutOfMemoryError

Java 內(nèi)存泄露

????一般來說內(nèi)存泄漏有兩種情況。一種情況如在 C/C++ 語言中的,在堆中的分配的內(nèi)存,在沒有將其釋放掉的時(shí)候,就將所有能訪問這塊內(nèi)存的方式都刪掉(如指針重新賦值);另一種情況則是在內(nèi)存對(duì)象明明已經(jīng)不需要的時(shí)候,還仍然保留著這塊內(nèi)存和它的訪問方式(引用)。第一種情況,在 Java 中已經(jīng)由于垃圾回收機(jī)制的引入,得到了很好的解決。所以, Java 中的內(nèi)存泄漏,主要指的是第二種情況。

????可能光說概念太抽象了,大家可以看一下這樣的例子:

1 ? Vector?v = new ?Vector( 10 );
2 ? for ?( int ?i = 1 ;i < 100 ;?i ++ ){
3 ? Object?o = new ?Object();
4 ? v.add(o);
5 ? o = null ;
6 ? }

???
????在這個(gè)例子中,代碼棧中存在 Vector 對(duì)象的引用 v Object 對(duì)象的引用 o 。在 For 循環(huán)中,我們不斷的生成新的對(duì)象,然后將其添加到 Vector 對(duì)象中,之后將 o 引用置空。問題是當(dāng) o 引用被置空后,如果發(fā)生 GC ,我們創(chuàng)建的 Object 對(duì)象是否能夠被 GC 回收呢?答案是否定的。因?yàn)椋? GC 在跟蹤代碼棧中的引用時(shí),會(huì)發(fā)現(xiàn) v 引用,而繼續(xù)往下跟蹤,就會(huì)發(fā)現(xiàn) v 引用指向的內(nèi)存空間中又存在指向 Object 對(duì)象的引用。也就是說盡管 o 引用已經(jīng)被置空,但是 Object 對(duì)象仍然存在其他的引用,是可以被訪問到的,所以 GC 無法將其釋放掉。如果在此循環(huán)之后, Object 對(duì)象對(duì)程序已經(jīng)沒有任何作用,那么我們就認(rèn)為此 Java 程序發(fā)生了內(nèi)存泄漏。

????盡管對(duì)于 C/C++ 中的內(nèi)存泄露情況來說, Java 內(nèi)存泄露導(dǎo)致的破壞性小,除了少數(shù)情況會(huì)出現(xiàn)程序崩潰的情況外,大多數(shù)情況下程序仍然能正常運(yùn)行。但是,在移動(dòng)設(shè)備對(duì)于內(nèi)存和 CPU 都有較嚴(yán)格的限制的情況下, Java 的內(nèi)存溢出會(huì)導(dǎo)致程序效率低下、占用大量不需要的內(nèi)存等問題。這將導(dǎo)致整個(gè)機(jī)器性能變差,嚴(yán)重的也會(huì)引起拋出 OutOfMemoryError ,導(dǎo)致程序崩潰。

一般情況下內(nèi)存泄漏的避免

????在不涉及復(fù)雜數(shù)據(jù)結(jié)構(gòu)的一般情況下, Java 的內(nèi)存泄露表現(xiàn)為一個(gè)內(nèi)存對(duì)象的生命周期超出了程序需要它的時(shí)間長度。我們有時(shí)也將其稱為“對(duì)象游離”。

例如:

?1 ? public ? class ?FileSearch{
?2 ?
?3 ? ???? private ? byte []?content;
?4 ? ???? private ?File?mFile;
?5 ? ????
?6 ? ???? public ?FileSearch(File?file){
?7 ? ????????mFile? = ?file;
?8 ? ????}
?9 ?
10 ? ???? public ? boolean ?hasString(String?str){
11 ? ???????? int ?size? = ?getFileSize(mFile);
12 ? ????????content? = ? new ? byte [size];
13 ? ????????loadFile(mFile,?content);
14 ? ????????
15 ? ????????String?s? = ? new ?String(content);
16 ? ???????? return ?s.contains(str);
17 ? ????}
18 ? }


????在這段代碼中, FileSearch 類中有一個(gè)函數(shù)
hasString ,用來判斷文檔中是否含有指定的字符串。流程是先將 mFile 加載到內(nèi)存中,然后進(jìn)行判斷。但是,這里的問題是,將 content 聲明為了實(shí)例變量,而不是本地變量。于是,在此函數(shù)返回之后,內(nèi)存中仍然存在整個(gè)文件的數(shù)據(jù)。而很明顯,這些數(shù)據(jù)我們后續(xù)是不再需要的,這就造成了內(nèi)存的無故浪費(fèi)。

????要避免這種情況下的內(nèi)存泄露,要求我們以 C/C++ 的內(nèi)存管理思維來管理自己分配的內(nèi)存。第一,是在聲明對(duì)象引用之前,明確內(nèi)存對(duì)象的有效作用域。在一個(gè)函數(shù)內(nèi)有效的內(nèi)存對(duì)象,應(yīng)該聲明為 local 變量,與類實(shí)例生命周期相同的要聲明為實(shí)例變量……以此類推。第二,在內(nèi)存對(duì)象不再需要時(shí),記得手動(dòng)將其引用置空。

復(fù)雜數(shù)據(jù)結(jié)構(gòu)中的內(nèi)存泄露問題

????在 實(shí)際的項(xiàng)目中,我們經(jīng)常用到一些較為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)用于緩存程序運(yùn)行過程中需要的數(shù)據(jù)信息。有時(shí),由于數(shù)據(jù)結(jié)構(gòu)過于復(fù)雜,或者我們存在一些特殊的需求(例 如,在內(nèi)存允許的情況下,盡可能多的緩存信息來提高程序的運(yùn)行速度等情況),我們很難對(duì)數(shù)據(jù)結(jié)構(gòu)中數(shù)據(jù)的生命周期作出明確的界定。這個(gè)時(shí)候,我們可以使用 Java 中一種特殊的機(jī)制來達(dá)到防止內(nèi)存泄露的目的。

????之前我們介紹過, Java GC 機(jī)制是建立在跟蹤內(nèi)存的引用機(jī)制上的。而在此之前,我們所使用的引用都只是定義一個(gè)“ Object?o; ”這樣形式的。事實(shí)上,這只是 Java 引用機(jī)制中的一種默認(rèn)情況,除此之外,還有其他的一些引用方式。通過使用這些特殊的引用機(jī)制,配合 GC 機(jī)制,就可以達(dá)到一些我們需要的效果。

Java 中的幾種引用方式

????Java 中有幾種不同的引用方式,它們分別是:強(qiáng)引用、軟引用、弱引用和虛引用。下面,我們首先詳細(xì)地了解下這幾種引用方式的意義。

????
????? 強(qiáng)引用

在此之前我們介紹的內(nèi)容中所使用的引用 都是強(qiáng)引用,這是使用最普遍的引用。如果一個(gè)對(duì)象具有強(qiáng)引用,那就類似于必不可少的生活用品,垃圾回收器絕不會(huì)回收它。當(dāng)內(nèi)存空?間不足, Java 虛擬機(jī)寧愿拋出 OutOfMemoryError 錯(cuò)誤,使程序異常終止,也不會(huì)靠隨意回收具有強(qiáng)引用的對(duì)象來解決內(nèi)存不足問題。

軟引用( SoftReference

SoftReference? 類的一個(gè)典型用途就是用于內(nèi)存敏感的高速緩存。 SoftReference? 的原理是:在保持對(duì)對(duì)象的引用時(shí)保證在? JVM? 報(bào)告內(nèi)存不足情況之前將清除所有的軟引用。關(guān)鍵之處在于,垃圾收集器在運(yùn)行時(shí)可能會(huì)(也可能不會(huì))釋放軟可及對(duì)象。對(duì)象是否被釋放取決于垃圾收集器的算法?以及垃圾收集器運(yùn)行時(shí)可用的內(nèi)存數(shù)量。

弱引用( WeakReference

WeakReference? 類的一個(gè)典型用途就是規(guī)范化映射( canonicalized?mapping )。另外,對(duì)于那些生存期相對(duì)較長而且重新創(chuàng)建的開銷也不高的對(duì)象來說,弱引用也比較有用。關(guān)鍵之處在于,垃圾收集器運(yùn)行時(shí)如果碰到了弱可及對(duì)象,將釋放? WeakReference? 引用的對(duì)象。然而,請(qǐng)注意,垃圾收集器可能要運(yùn)行多次才能找到并釋放弱可及對(duì)象。

虛引用( PhantomReference

PhantomReference? 類只能用于跟蹤對(duì)被引用對(duì)象即將進(jìn)行的收集。同樣,它還能用于執(zhí)行? pre-mortem? 清除操作。 PhantomReference? 必須與? ReferenceQueue? 類一起使用。需要? ReferenceQueue? 是因?yàn)樗軌虺洚?dāng)通知機(jī)制。當(dāng)垃圾收集器確定了某個(gè)對(duì)象是虛可及對(duì)象時(shí), PhantomReference? 對(duì)象就被放在它的? ReferenceQueue? 上。將? PhantomReference? 對(duì)象放在? ReferenceQueue? 上也就是一個(gè)通知,表明? PhantomReference? 對(duì)象引用的對(duì)象已經(jīng)結(jié)束,可供收集了。這使您能夠剛好在對(duì)象占用的內(nèi)存被回收之前采取行動(dòng)。 Reference ReferenceQueue 的配合使用。

GC Reference ReferenceQueue 的交互

A、? GC 無法刪除存在強(qiáng)引用的對(duì)象的內(nèi)存。

B、? GC 發(fā)現(xiàn)一個(gè)只有軟引用的對(duì)象內(nèi)存,那么:

①? SoftReference 對(duì)象的 referent? 域被設(shè)置為 null ,從而使該對(duì)象不再引用 heap 對(duì)象。

②? SoftReference 引用過的 heap 對(duì)象被聲明為 finalizable

③? 當(dāng)? heap? 對(duì)象的? finalize()? 方法被運(yùn)行而且該對(duì)象占用的內(nèi)存被釋放, SoftReference? 對(duì)象就被添加到它的? ReferenceQueue (如果后者存在的話)。

C、? GC 發(fā)現(xiàn)一個(gè)只有弱引用的對(duì)象內(nèi)存,那么:

①? WeakReference 對(duì)象的 referent 域被設(shè)置為 null , 從而使該對(duì)象不再引用 heap 對(duì)象。

②? WeakReference 引用過的 heap 對(duì)象被聲明為 finalizable

③? 當(dāng) heap 對(duì)象的 finalize() 方法被運(yùn)行而且該對(duì)象占用的內(nèi)存被釋放時(shí), WeakReference 對(duì)象就被添加到它的 ReferenceQueue (如果后者存在的話)。

D、? GC 發(fā)現(xiàn)一個(gè)只有虛引用的對(duì)象內(nèi)存,那么:

①? PhantomReference 引用過的 heap 對(duì)象被聲明為 finalizable

②? PhantomReference 在堆對(duì)象被釋放之前就被添加到它的 ReferenceQueue

值得注意的地方有以下幾點(diǎn):

1 GC 在一般情況下不會(huì)發(fā)現(xiàn)軟引用的內(nèi)存對(duì)象,只有在內(nèi)存明顯不足的時(shí)候才會(huì)發(fā)現(xiàn)并釋放軟引用對(duì)象的內(nèi)存。

2 GC 對(duì)弱引用的發(fā)現(xiàn)和釋放也不是立即的,有時(shí)需要重復(fù)幾次 GC ,才會(huì)發(fā)現(xiàn)并釋放弱引用的內(nèi)存對(duì)象。
3 、軟引用和弱引用在添加到 ReferenceQueue 的時(shí)候,其指向真實(shí)內(nèi)存的引用已經(jīng)被置為空了,相關(guān)的內(nèi)存也已經(jīng)被釋放掉了。而虛引用在添加到 ReferenceQueue 的時(shí)候,內(nèi)存還沒有釋放,仍然可以對(duì)其進(jìn)行訪問。

????代碼示例

通過以上的介紹,相信您對(duì) Java 的引用機(jī)制以及幾種引用方式的異同已經(jīng)有了一定了解。光是概念,可能過于抽象,下面我們通過一個(gè)例子來演示如何在代碼中使用 Reference 機(jī)制。

1 ? ????String?str? = ? new ?String( " hello " );? //
2 ? ????ReferenceQueue < String > ?rq? = ? new ?ReferenceQueue < String > ();? //
3 ? ????WeakReference < String > ?wf? = ? new ?WeakReference < String > (str,?rq);? //
4 ? ????str = null ;? // ④取消"hello"對(duì)象的強(qiáng)引用
5 ? ????String?str1 = wf.get();? // ⑤假如"hello"對(duì)象沒有被回收,str1引用"hello"對(duì)象
6 ? ???? // 假如"hello"對(duì)象沒有被回收,rq.poll()返回null
7 ? ????Reference <? ? extends ?String > ?ref = rq.poll();? //


在以上代碼中,注意⑤⑥兩處地方。假如“ hello ”對(duì)象沒有被回收 wf.get() 將返回“ hello ”字符串對(duì)象, rq.poll() 返回 null ;而加入“ hello ”對(duì)象已經(jīng)被回收了,那么 wf.get() 返回 null rq.poll() 返回 Reference 對(duì)象,但是此 Reference 對(duì)象中已經(jīng)沒有 str 對(duì)象的引用了 ( PhantomReference 則與 WeakReference SoftReference 不同 )

????引用機(jī)制與復(fù)雜數(shù)據(jù)結(jié)構(gòu)的聯(lián)合應(yīng)用

????了解了 GC 機(jī)制、引用機(jī)制,并配合上 ReferenceQueue ,我們就可以實(shí)現(xiàn)一些防止內(nèi)存溢出的復(fù)雜數(shù)據(jù)類型。

例如, SoftReference 具有構(gòu)建 Cache 系統(tǒng)的特質(zhì),因此我們可以結(jié)合哈希表實(shí)現(xiàn)一個(gè)簡單的緩存系統(tǒng)。這樣既能保證能夠盡可能多的緩存信息,又可以保證 Java 虛擬機(jī)不會(huì)因?yàn)閮?nèi)存泄露而拋出 OutOfMemoryError 。這種緩存機(jī)制特別適合于內(nèi)存對(duì)象生命周期長,且生成內(nèi)存對(duì)象的耗時(shí)比較長的情況,例如緩存列表封面圖片等。對(duì)于一些生命周期較長,但是生成內(nèi)存對(duì)象開銷不大的情況,使用 WeakReference 能夠達(dá)到更好的內(nèi)存管理的效果。

SoftHashmap 的源碼一份,相信看過之后,大家會(huì)對(duì) Reference 機(jī)制的應(yīng)用有更深入的理解。

??1 package ?com. *** .widget;
??2
??3 // :?SoftHashMap.java?
??4 import ?java.util. * ;?
??5 import ?java.lang.ref. * ;?
??6
??7 import ?android.util.Log;
??8
??9 public ? class ?SoftHashMap? extends ?AbstractMap? {?
?10 ?? /** ?The?internal?HashMap?that?will?hold?the?SoftReference.? */ ?
?11 ?? private ? final ?Map?hash? = ? new ?HashMap();?
?12 ?? /** ?The?number?of?"hard"?references?to?hold?internally.? */ ?
?13 ?? private ? final ? int ?HARD_SIZE;?
?14 ?? /** ?The?FIFO?list?of?hard?references,?order?of?last?access.? */ ?
?15 ?? private ? final ?LinkedList?hardCache? = ? new ?LinkedList();?
?16 ?? /** ?Reference?queue?for?cleared?SoftReference?objects.? */ ?
?17 ?? private ?ReferenceQueue?queue? = ? new ?ReferenceQueue();?
?18
?19 ?? // Strong?Reference?number
?20 ?? public ?SoftHashMap()? {? this ( 100 );?} ?
?21 ?? public ?SoftHashMap( int ?hardSize)? {?HARD_SIZE? = ?hardSize;?} ?
?22 ??
?23
?24 ?? public ?Object?get(Object?key)? {?
?25 ????Object?result? = ? null ;?
?26 ???? // ?We?get?the?SoftReference?represented?by?that?key?
?27 ????SoftReference?soft_ref? = ?(SoftReference)hash.get(key);?
?28 ???? if ?(soft_ref? != ? null )? {?
?29 ?????? // ?From?the?SoftReference?we?get?the?value,?which?can?be?
?30 ?????? // ?null?if?it?was?not?in?the?map,?or?it?was?removed?in?
?31 ?????? // ?the?processQueue()?method?defined?below?
?32 ??????result? = ?soft_ref.get();?
?33 ?????? if ?(result? == ? null )? {?
?34 ???????? // ?If?the?value?has?been?garbage?collected,?remove?the?
?35 ???????? // ?entry?from?the?HashMap.?
?36 ????????hash.remove(key);?
?37 ??????}
? else ? {?
?38 ???????? // ?We?now?add?this?object?to?the?beginning?of?the?hard?
?39 ???????? // ?reference?queue.??One?reference?can?occur?more?than?
?40 ???????? // ?once,?because?lookups?of?the?FIFO?queue?are?slow,?so?
?41 ???????? // ?we?don't?want?to?search?through?it?each?time?to?remove?
?42 ???????? // ?duplicates.?
?43 ?????????? // keep?recent?use?object?in?memory
?44 ????????hardCache.addFirst(result);?
?45 ???????? if ?(hardCache.size()? > ?HARD_SIZE)? {?
?46 ?????????? // ?Remove?the?last?entry?if?list?longer?than?HARD_SIZE?
?47 ??????????hardCache.removeLast();?
?48 ????????}
?
?49 ??????}
?
?50 ????}
?
?51 ???? return ?result;?
?52 ??}
?
?53
?54 ?? /** ?We?define?our?own?subclass?of?SoftReference?which?contains?
?55 ???not?only?the?value?but?also?the?key?to?make?it?easier?to?find?
?56 ???the?entry?in?the?HashMap?after?it's?been?garbage?collected.? */
?
?57 ?? private ? static ? class ?SoftValue? extends ?SoftReference? {?
?58 ???? private ? final ?Object?key;? // ?always?make?data?member?final?
?59 ???? /** ?Did?you?know?that?an?outer?class?can?access?private?data?
?60 ?????members?and?methods?of?an?inner?class???I?didn't?know?that!?
?61 ?????I?thought?it?was?only?the?inner?class?who?could?access?the?
?62 ?????outer?class's?private?information.??An?outer?class?can?also?
?63 ?????access?private?members?of?an?inner?class?inside?its?inner?
?64 ?????class.? */
?
?65 ???? private ?SoftValue(Object?k,?Object?key,?ReferenceQueue?q)? {?
?66 ?????? super (k,?q);?
?67 ?????? this .key? = ?key;?
?68 ????}
?
?69 ??}
?
?70
?71 ?? /** ?Here?we?go?through?the?ReferenceQueue?and?remove?garbage?
?72 ???collected?SoftValue?objects?from?the?HashMap?by?looking?them?
?73 ???up?using?the?SoftValue.key?data?member.? */
?
?74 ?? public ? void ?processQueue()? {?
?75 ????SoftValue?sv;?
?76 ???? while ?((sv? = ?(SoftValue)queue.poll())? != ? null )? {?
?77 ???????? if (sv.get() == ? null ) {
?78 ????????????Log.e( " processQueue " ,? " null " );
?79 ????????}
else {
?80 ????????????Log.e( " processQueue " ,? " Not?null " );
?81 ????????}

?82 ??????hash.remove(sv.key);? // ?we?can?access?private?data!
?83 ??????Log.e( " SoftHashMap " ,? " release? " ? + ?sv.key);
?84 ????}
?
?85 ??}
?
?86 ?? /** ?Here?we?put?the?key,?value?pair?into?the?HashMap?using?
?87 ???a?SoftValue?object.? */
?
?88 ?? public ?Object?put(Object?key,?Object?value)? {?
?89 ????processQueue();? // ?throw?out?garbage?collected?values?first?
?90 ????Log.e( " SoftHashMap " ,? " put?into? " ? + ?key);
?91 ???? return ?hash.put(key,? new ?SoftValue(value,?key,?queue));?
?92 ??}
?
?93 ?? public ?Object?remove(Object?key)? {?
?94 ????processQueue();? // ?throw?out?garbage?collected?values?first?
?95 ???? return ?hash.remove(key);?
?96 ??}
?
?97 ?? public ? void ?clear()? {?
?98 ????hardCache.clear();?
?99 ????processQueue();? // ?throw?out?garbage?collected?values?
100 ????hash.clear();?
101 ??}
?
102 ?? public ? int ?size()? {?
103 ????processQueue();? // ?throw?out?garbage?collected?values?first?
104 ???? return ?hash.size();?
105 ??}
?
106 ?? public ?Set?entrySet()? {?
107 ???? // ?no,?no,?you?may?NOT?do?that!!!?GRRR?
108 ???? throw ? new ?UnsupportedOperationException();?
109 ??}
?
110 }
?
111
112
113

Java內(nèi)存泄露的理解與解決


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 墨竹工卡县| 淮阳县| 孙吴县| 富宁县| 雷州市| 财经| 喀喇沁旗| 噶尔县| 鄯善县| 合阳县| 孟连| 蒲城县| 蕲春县| 全州县| 稻城县| 长寿区| 佳木斯市| 玉田县| 南投县| 桃江县| 二连浩特市| 乐都县| 炎陵县| 临猗县| 衡水市| 鹤峰县| 榆林市| 铁岭县| 黑山县| 全椒县| 博罗县| 锦屏县| 昔阳县| 常山县| 莆田市| 洛阳市| 苍山县| 驻马店市| 沁阳市| 包头市| 高尔夫|