本文目錄一覽:
- 1、java中靜態類變數不使用會被回收嗎?
- 2、java 內存回收不了什麼原因
- 3、java 怎麼把數據存到內存中
- 4、java集合類中有對對象的引用,使用完後未清空,使得JVM不能回收(求例子)並且附上解決方法
- 5、java google 的內存緩存為什麼總調用cacheloader
- 6、Java中資料庫連接池是如何做到,將Connection作為對象放入內存中不被回收機回收?
java中靜態類變數不使用會被回收嗎?
靜態類變數不會被釋放。只有等應用結束才釋放。
1、靜態類只有在內部類的時候才能被應用
2、靜態類在應用初始化時就放在靜態方法區中,是公共共享,應用結束才能回收靜態方法區。
java 內存回收不了什麼原因
垃圾回收(garbagecollection,簡稱GC)可以自動清空堆中不再使用的對象。垃圾回收機制最早出現於1959年,被用於解決Lisp語言中的問題。垃圾回收是Java的一大特徵。並不是所有的語言都有垃圾回收功能。比如在C/C++中,並沒有垃圾回收的機制。程序員需要手動釋放堆中的內存。由於不需要手動釋放內存,程序員在編程中也可以減少犯錯的機會。利用垃圾回收,程序員可以避免一些指針和內存泄露相關的bug(這一類bug通常很隱蔽)。但另一方面,垃圾回收需要耗費的計算時間。垃圾回收實際上是將原本屬於程序員的責任轉移給計算機。使用垃圾回收的程序需要更長的運行時間。在Java中,對象的是通過引用使用的(把對象相像成致命的毒物,引用就像是用於提取毒物的鑷子)。如果不再有引用指向對象,那麼程序員就再也無從調用或者處理該對象。這樣的對象將不可到達(unreachable)。垃圾回收用於釋放不可到達對象所佔據的內存。這是垃圾回收的基本原則。(不可到達對象是死對象,是垃圾回收所要回收的垃圾)早期的垃圾回收採用引用計數(referencecounting)的機制。每個對象包含一個計數器。當有新的指向該對象的引用時,計數器加1。當引用移除時,計數器減1。當計數器為0時,認為該對象可以進行垃圾回收。然而,一個可能的問題是,如果有兩個對象循環引用(cyclicreference),比如兩個對象互相引用,而且此時沒有其它(指向A或者指向B)的引用,程序員實際上根本無法通過引用到達這兩個對象。因此,程序員以棧和static數據為根(root),從根出發,跟隨所有的引用,就可以找到所有的可到達對象。也就是說,一個可到達對象,一定被根引用,或者被其他可到達對象引用。
java 怎麼把數據存到內存中
這裡你採納與否沒關係,給你說說編程與內存的關係。
你定義的任何變數,常量,類,方法等等,其實都在內存中,沒有所謂的把數據存內存中,這概念,你可以想一下電腦重啟或關機後,內存中的所有數據,都會丟失,除非你保存到磁碟中去。
在內存中的數據有兩塊,第一、緩衝,一般寫數據到磁碟的時候開闢出來的內存空間;第二、緩存,一般是從磁碟讀數據到內存中開闢出來的內存空間。會這麼使用,原因很簡單,磁碟讀寫數據速度與內存不一致(磁碟的存取效率遠遠小於內存的存取效率),為了提高數據的存取效率,才會這麼乾的。
一般而言,java中的所謂數據,大部分都是類,從自動引用計數的概念來分析,你想把對象長久的放在內存中,不會被垃圾回收機制釋放,注意製藥有一個對象在使用/引用你的數據,這條數據就會存在內存中。所以,想servlet中的全局配置參數,隨時可以取到還是唯一一份,你可以參考一下。
另外內存使用分堆與棧,堆在面向對象編程中存儲對象的,棧是方法或函數執行的時候臨時開闢的存儲空間,方法或函數執行完畢就會釋放。
希望我的回復能幫助到你,採納與否沒關係。有更好的答案,我就隱藏我的回復。
java集合類中有對對象的引用,使用完後未清空,使得JVM不能回收(求例子)並且附上解決方法
我明白你的意思。
這種情況可能的結果是出現異常類:OutOfMemoryError(內存溢出)。
產生的原因其中之一就是 集合類中對對象的引用,使用完未清空,使得JVM不能回收。
可以這樣子清空,代碼如下:
Set set = new HashSet();
/*中間這部分是使用set的代碼…,最後clear()清空*/
set.clear();
隨信附上出現內存溢出異常時常用的解決辦法(轉自Java面試那些事):
檢查代碼中是否有死循環或遞歸調用。
檢查是否有大循環重複產生新對象實體。
檢查對資料庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,資料庫中數據較少,不容易出問題,上線後,資料庫中數據多了,一次查詢可能就會引起內存溢出。因此對於資料庫查詢盡量採用分頁的方式查詢。
檢查List、Map等集合對象是否使用完未清除的問題,List、Map等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收。
檢查對大文件的讀取是否採用nio的方式。(這塊我不懂,你可以百度看看,也歡迎你跟我交流。)
望採納,謝謝。(●’◡’●)
java google 的內存緩存為什麼總調用cacheloader
首先,看一下使用範例:
Java代碼
LoadingCacheKey,Graph graphs =CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10,TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
newCacheLoaderKey,Graph(){
publicGraph load(Key key)throwsAnyException{
return createExpensiveGraph(key);
}
});
適用性
緩存在很多情況下都是非常有用的。比如,我們需要多次根據給定的輸入獲取值,而且該值計算或者獲取的開銷是非常昂貴的。
緩存和ConcurrentMap是非常相像的,但是它們也不完全一樣。最根本的區別就是,ConcurrentMap會持有所有添加的對象,直到被顯示的移除。而緩存為了限制其內存的使用,通常都會配置成可以自動的將對象移除。在某些情況下即使不自動移除對象也是非常有用的,如LoadingCache它會自動載入緩存對象。
一般,Guava緩存適用於以下幾種情況:
你願意花費一些內存來換取性能提升;
你預測到某些鍵會多次進行查詢;
你的緩存數據不超過內存(Guava緩存是單個應用中的本地緩存。它不會將數據存儲到文件中,或者外部伺服器。如果不適合你,可以考慮一下 Memcached)。
如果你的需要符合上面所說的每一條,那麼選擇Guava緩存絕對沒錯。
使用CacheBuilder的構建模式可以獲取一個Cache,如上面的範例所示。但是如何進行定製才是比較有趣的。
注意:如果你不需要緩存的這些特性,那麼使用ConcurrentHashMap會有更好的內存效率,但是如果想基於舊有的ConcurrentMap複製實現Cache的一些特性,那麼可能是非常困難或者根本不可能。
載入
對於緩存首先需要明確的是:有沒有一個方法可以通過給定的鍵來計算/載入相應的值?如果有,那麼可以使用CacheLoader。如果沒有這樣的方法,或者你想複寫緩存的載入方式,但你仍想保留「get-if-absent-compute」語義,你可以在調用get方法時傳入一個Callable實例,來達到目的。緩存的對象可以通過Cache.put直接插入,但是自動載入是首選,因為自動載入可以更加容易的判斷所有緩存信息的一致性。
From a CacheLoader
LoadingCache 緩存是通過一個CacheLoader來構建緩存。創建一個CacheLoader僅需要實現V load(K key) throws Exception方法即可。下面的範例就是如何創建一個LoadingCache:
Java代碼
LoadingCacheKey,Graph graphs =CacheBuilder.newBuilder()
.maximumSize(1000)
.build(
newCacheLoaderKey,Graph(){
publicGraph load(Key key)throwsAnyException{
return createExpensiveGraph(key);
}
});
…
try{
return graphs.get(key);
}catch(ExecutionException e){
thrownewOtherException(e.getCause());
}
通過方法get(K)可以對LoadingCache進行查詢。該方法要不返回已緩存的值,要不通過CacheLoader來自動載入相應的值到緩存中。這裡需要注意的是:CacheLoader可能會拋出Exception,LoaderCache.get(K)則可能會拋出ExecutionException。假如你定義的CacheLoader沒有聲明檢查型異常,那麼可以通過調用getUnchecked(K)來獲取緩存值;但是一旦當CacheLoader中聲明了檢查型異常,則不可以調用getUnchecked。
Java代碼
LoadingCacheKey,Graph graphs =CacheBuilder.newBuilder()
.expireAfterAccess(10,TimeUnit.MINUTES)
.build(
newCacheLoaderKey,Graph(){
publicGraph load(Key key){// no checked exception
return createExpensiveGraph(key);
}
});
…
return graphs.getUnchecked(key);
批量查詢可以使用getAll(Iterable? extends K)方法。預設,getAll方法將循環每一個鍵調用CacheLoader.load方法獲取緩存值。當緩存對象的批量獲取比單獨獲取更有效時,可以通過複寫CacheLoader.loadAll方法實現緩存對象的載入。此時當調用getAll(Iterable)方法時性能也會提升。
需要注意的是CacheLoader.loadAll的實現可以為沒有明確要求的鍵載入緩存值。比如,當為某組中的一些鍵進行計算時,loadAll方法則可能會同時載入組中其餘鍵的值。
From a Callable
所有Guava緩存,不論是否會自動載入,都支持get(K, Callable(V))方法。當給定鍵的緩存值已存在時則直接返回,否則通過指定的Callable方法進行計算並將值存放到緩存中。直到載入完成時,相應的緩存才會被更改。該方法簡單實現了”if cached, return; otherwise create, cache and return”語義。
Java代碼
CacheKey,Value cache =CacheBuilder.newBuilder()
.maximumSize(1000)
.build();// look Ma, no CacheLoader
…
try{
// If the key wasn’t in the “easy to compute” group, we need to
// do things the hard way.
cache.get(key,newCallableValue(){
@Override
publicValue call()throwsAnyException{
return doThingsTheHardWay(key);
}
});
}catch(ExecutionException e){
thrownewOtherException(e.getCause());
}
直接插入
使用cache.put(key, value)方法可以將值直接插入到緩存中,但這將會覆蓋緩存中已存在的值。通過使用Cache.asMap()所導出的ConcurrentMap對象中的方法也可以對緩存進行修改。但是,請注意asMap中的任何方法都不能自動的將數據載入到緩存中。也就是說,asMap中的各方法是在緩存自動載入範圍之外來運作。所以,當你使用CacheLoader或Callable來載入緩存時,應該優先使用Cache.get(K, CallableV),而不是Cache.asMap().putIfAbsent。
緩存回收
殘酷的現實是我們可以肯定的說我們沒有足夠的內存來緩存一切。你必須來決定:什麼時候緩存值不再值得保留?Guava提供了三種基本的緩存回收策略:基於容量回收策略,基於時間回收策略,基於引用回收策略。
基於容量回收策略
使用CacheBuilder.maximumSize(long)可以設置緩存的最大容量。緩存將會嘗試回收最近沒有使用,或者沒有經常使用的緩存項。警告:緩存可能會在容量達到限制之前執行回收,通常是在緩存大小逼近限制大小時。
另外,如果不同的緩存項有不同的「權重」, 如,緩存項有不同的內存佔用,此時你需要使用CacheBuilder.weigher(Weigher)指定一個權重計算函數,並使用CacheBuilder.maxmumWeight(long)設定總權重。和maximumSize同樣需要注意的是緩存也是在逼近總權重的時候進行回收處理。此外,緩存項的權重是在創建時進行計算,此後不再改變。
Java代碼
LoadingCacheKey,Graph graphs =CacheBuilder.newBuilder()
.maximumWeight(100000)
.weigher(
newWeigherKey,Graph(){
publicint weigh(Key k,Graph g){
return g.vertices().size();
}
})
.build(
newCacheLoaderKey,Graph(){
publicGraph load(Key key){// no checked exception
return createExpensiveGraph(key);
}
});
基於時間回收策略
CacheBuilder為基於時間的回收提供了兩種方式:
expireAfterAccess(long, TimeUnit) 當緩存項在指定的時間段內沒有被讀或寫就會被回收。這種回收策略類似於基於容量回收策略;
expireAfterWrite(long, TimeUnit) 當緩存項在指定的時間段內沒有更新就會被回收。如果我們認為緩存數據在一段時間後數據不再可用,那麼可以使用該種策略。
就如下面的討論,定時過期回收會在寫的過程中周期執行,偶爾也會讀的過程中執行。
測試定時回收
測試定時回收其實不需要那麼痛苦的,我們不必非得花費2秒來測試一個2秒的過期。在構建緩存時使用Ticker介面,並通過CacheBuilder.ticker(Ticker)方法指定時間源,這樣我們就不用傻乎乎等系統時鐘慢慢的走了。
基於引用回收策略
通過鍵或緩存值的弱引用(weak references),或者緩存值的軟引用(soft references),Guava可以將緩存設置為允許垃圾回收。
CacheBuilder.weakKeys() 使用弱引用存儲鍵。當沒有(強或軟)引用到該鍵時,相應的緩存項將可以被垃圾回收。由於垃圾回收是依賴==進行判斷,因此這樣會導致整個緩存也會使用==來比較鍵的相等性,而不是使用equals();
CacheBuilder.weakValues() 使用弱引用存儲緩存值。當沒有(強或軟)引用到該緩存項時,將可以被垃圾回收。由於垃圾回收是依賴==進行判斷,因此這樣會導致整個緩存也會使用==來比較緩存值的相等性,而不是使用equals();
CacheBuilder.softValues() 使用軟引用存儲緩存值。當響應需要時,軟引用才會被垃圾回收通過最少使用原則回收掉。由於使用軟引用造成性能上的影響,我們強烈建議使用可被預言的maximum cache size的策略來代替。同樣使用softValues()緩存值的比較也是使用==,而不是equals()。
顯示移除
在任何時候,你都可以可以通過下面的方法顯式將無效的緩存移除,而不是被動等待被回收:
使用Cache.invalidate(key)單個移除;
使用Cache.invalidteAll(keys)批量移除;
使用Cache.invalidateAll()移除全部。
Java中資料庫連接池是如何做到,將Connection作為對象放入內存中不被回收機回收?
糾正下你的說法.一個類是不會無緣無故運行的,所以談不上佔用內存,更沒有回收.你問的應該是使用一個類創建了一個對象,如何回收該對象所佔的內存空間?
例如有一個Person類,我們創建他的一個對象,一般是如下:
Person mPerson = new Person();
這個時候情況是,在棧內存中標記了一個名字叫mPerson的空間,它存儲了一個關於某塊內存區域位置的信息,說白了,就是你使用new Person();創建出來的對象的位置,我們稱mPerson為Person對象的一個引用。這個對象位於堆內存,它是有默認值的,必須占內存一部分空間,想使用的時候,可以通過mPerson找到它。當你把mPerson賦值為null後,你那個對象就沒有引用了,這個時候,你的JVM會在適當的時候自動去回收掉Person的對象。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/301733.html