最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

理解Java垃圾回收

 更新時間:2016年03月27日 10:46:02   作者:趙杰A-124  
這篇文章主要幫助大家理解Java垃圾回收,通過實例學習java垃圾回收,什么是垃圾回收,感興趣的小伙伴們可以參考一下

當程序創(chuàng)建對象、數(shù)組等引用類型的實體時,系統(tǒng)會在堆內(nèi)存中為這一對象分配一塊內(nèi)存,對象就保存在這塊內(nèi)存中,當這塊內(nèi)存不再被任何引用變量引用時,這塊內(nèi)存就變成垃圾,等待垃圾回收機制進行回收。垃圾回收機制具有三個特征:

垃圾回收機制只負責回收堆內(nèi)存中的對象,不會回收任何物理資源(例如數(shù)據(jù)庫連接,打開的文件資源等),也不會回收以某種創(chuàng)建對象的方式以外的方式為該對像分配的內(nèi)存,(例如對象調(diào)用本地方法中malloc的方式申請的內(nèi)存)
程序無法精確控制垃圾回收的運行,只可以建議垃圾回收進行,建議的方式有兩種System.gc() 和Runtime.getRuntime().gc()
在垃圾回收任何對象之前,總會先調(diào)用它的finalize()方法,但是同垃圾回收的時機一致,調(diào)用finalize()方法的時機也不確定。
針對以上三個特征,有三個問題:

1、必須手動的進行清理工作,釋放除創(chuàng)建對象的方式以外的方式分配的內(nèi)存和其它的物理資源。并且要注意消除過期的對象引用,否則可能引起OOM。

手動清理通常用到try...finally...這樣的代碼結構。

示例如下:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ManualClear {

 public static void main(String[] args) {
  FileInputStream fileInputStream = null;
  try {
   fileInputStream = new FileInputStream("./src/ManualClear.java");
  } catch (FileNotFoundException e) {
   System.out.println(e.getMessage());
   e.printStackTrace();
   return;
  }

  try {
   byte[] bbuf = new byte[1024];
   int hasRead = 0;
   try {
    while ((hasRead = fileInputStream.read(bbuf)) > 0) {
     System.out.println(new String(bbuf, 0, hasRead));
    }
   } catch (IOException e) {
    e.printStackTrace();
   }
  } finally {
   try {
    fileInputStream.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }

}

對于過期對象的引用,引起的OOM通常有三種常見的情況,這三種情況通常都不易發(fā)現(xiàn),短時間內(nèi)運行也不會有什么問題,但是時間久了后,泄漏的對象增加后終會引起程序崩潰。

類自己管理內(nèi)存時,要警惕內(nèi)存泄漏
示例如下:

import java.util.Arrays;
import java.util.EmptyStackException;

class Stack{
 private Object[] elements;
 private int size;
 private static final int DEFAULT_INITAL_CAPACITY = 16;
 
 public Stack() {
  elements = new Object[DEFAULT_INITAL_CAPACITY];
 }
 
 public void push(Object e){
  ensureCapacity();
  elements[size++] = e;
 }
 
 public Object pop() {
  if (size == 0) {
   throw new EmptyStackException();
  }
  
  return elements[--size];
 }
 
 private void ensureCapacity() {
  if (elements.length == size) {
   elements = Arrays.copyOf(elements, 2 * size + 1);
  }
 }
}

public class StackDemo {
 
 public static void main(String[] args) {
  Stack stack = new Stack();
  
  for (int i = 0; i < 10000; i++) {
   stack.push(new Object());
  }
  
  for(int i = 0; i < 10000; i++) {
   stack.pop();
  }
 }

}

之所以會內(nèi)存泄漏,是因為那些出棧的對象即使程序其它對象不再引用,但是Stack類中的elements[]數(shù)組依然保存著這些對象的引用,導致這些對象不會被垃圾回收所回收,所以,當需要類自己管理內(nèi)存事,要警惕內(nèi)部維護的這些過期引用是否被及時解除了引用,本例中只需在出棧后,顯示的將

elements[size] = null;即可。

緩存是要警惕內(nèi)存泄漏
出現(xiàn)這樣情況通常是一旦將對象放入緩存,很可能長時間不使用很容易遺忘,通常可以用WakeHashMap代表緩存,在緩存中的項過期后,他們可以被自動刪除?;蛘呖梢杂梢粋€后臺線程定期執(zhí)行來清除緩沖中的過期項。

監(jiān)聽器或回調(diào)的注冊,最好可以顯示的取消注冊。
2、不要手動調(diào)用finalize(),它是給垃圾回收器調(diào)用的

3、避免使用finalize()方法,除非用來作為判斷終結條件以發(fā)現(xiàn)對象中沒有被適當清理的部分;用來作為安全網(wǎng)在手動清理忘記調(diào)用的情況下清理系統(tǒng)資源,延后清理總別永不清理要強,并且如果同時記錄下忘記清理資源的信息的話,也方便后面發(fā)現(xiàn)錯誤,并及時修改忘記清理的代碼;釋放對象中本地方法獲得的不是很關鍵的系統(tǒng)資源。

finalize()方法由于其執(zhí)行時間以及是否確定被執(zhí)行都不能準確確保,所以最好不用來釋放關鍵資源,但是可用于上面所說的三種情況。其中第一種情況,示例如下:

class Book {
 boolean checkout = false;
 public Book(boolean checkout) {
  this.checkout = checkout;
 }
 
 public void checkin(){
  checkout = false;
 }
 
 @Override
 protected void finalize() throws Throwable {
  if (checkout) {
   System.out.println("Error: check out");
  }
 }
}

public class FinalizeCheckObjectUse {

 public static void main(String[] args) {
  new Book(true);
  System.gc();
 }

}

執(zhí)行結果:

Error: check out
例子中的Book對象,在釋放前必須處于checkIn的狀態(tài),否則不能釋放,finalize中的實現(xiàn)可以幫助及時發(fā)現(xiàn)不合法的對象,或者更直接的,在finalize中直接使用某個引用變量引用,使其重新進入reachable的狀態(tài),然后再次對其進行處理。

另一點需要注意的時,子類如果覆蓋了父類的finalize方法,但是忘了手工調(diào)用super.finalize或者子類的finalize過程出現(xiàn)異常導致沒有執(zhí)行到super.finalize時,那么父類的終結方法將永遠不會調(diào)到。

如下:

class Parent{
  @Override
  protected void finalize() throws Throwable {
    System.out.println(getClass().getName() + " finalize start");
  }
}

class Son extends Parent{
  @Override
  protected void finalize() throws Throwable {
    System.out.println(getClass().getName() + " finalize start");
  }
}
public class SuperFinalizeLost {

  public static void main(String[] args) {
    new Son();
    System.gc();
  }

}

運行結果:

Son finalize start
或者

class Parent{
  @Override
  protected void finalize() throws Throwable {
    System.out.println(getClass().getName() + " finalize start");
  }
}

class Son extends Parent{
  @Override
  protected void finalize() throws Throwable {
    System.out.println(getClass().getName() + " finalize start");
    int i = 5 / 0;
    super.finalize();
  }
}
public class SuperFinalizeLost {

  public static void main(String[] args) {
    new Son();
    System.gc();
  }

}

執(zhí)行結果:

Son finalize start
對于第二種情況,可以使用try...finally...結構解決,但是對于第一種情況,最好使用一種叫終結方法守護者的方式。示例如下

class Parent2{
  private final Object finalizeGuardian = new Object() {
    protected void finalize() throws Throwable {
      System.out.println("在此執(zhí)行父類終結方法中的邏輯");
    };
  };
}

class Son2 extends Parent2{
  @Override
  protected void finalize() throws Throwable {
    System.out.println(getClass().getName() + " finalize start");
    int i = 5 / 0;
    super.finalize();
  }
}

public class FinalizeGuardian {

  public static void main(String[] args) {
    new Son2();
    System.gc();
  }

}

執(zhí)行結果:

在此執(zhí)行父類終結方法中的邏輯
Son2 finalize start
這樣可以保證父類的終結方法中所需做的操作執(zhí)行到。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助。

相關文章

  • Java實現(xiàn)富文本轉(zhuǎn)markdown

    Java實現(xiàn)富文本轉(zhuǎn)markdown

    這篇文章主要為大家詳細介紹了如何通過Java實現(xiàn)富文本轉(zhuǎn)markdown功能,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考下
    2023-12-12
  • Java中的ThreadLocal與ThreadLocalMap詳解

    Java中的ThreadLocal與ThreadLocalMap詳解

    這篇文章主要介紹了Java中的ThreadLocal與ThreadLocalMap詳解,ThreadLocal 是一個線程局部變量,其實的功用非常簡單,就是為每一個使用該變量的線程都提供一個變量值的副本,是Java中一種較為特殊的線程綁定機制,需要的朋友可以參考下
    2023-09-09
  • Spring中配置ContextLoaderListener方式

    Spring中配置ContextLoaderListener方式

    這篇文章主要介紹了Spring中配置ContextLoaderListener方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Java鎖機制Lock用法示例

    Java鎖機制Lock用法示例

    這篇文章主要介紹了Java鎖機制Lock用法,結合具體實例形式分析了Java鎖機制的相關上鎖、釋放鎖、隱式鎖、顯式鎖等概念與使用技巧,需要的朋友可以參考下
    2018-08-08
  • Java中的靜態(tài)代碼塊與構造代碼塊詳解

    Java中的靜態(tài)代碼塊與構造代碼塊詳解

    靜態(tài)代碼塊在JVM加載類時執(zhí)行,僅執(zhí)行一次,用于初始化靜態(tài)變量或執(zhí)行一次性設置,構造代碼塊在每次創(chuàng)建對象時執(zhí)行,用于實例變量的初始化或執(zhí)行創(chuàng)建對象時的公共邏輯,靜態(tài)代碼塊按定義順序執(zhí)行,構造代碼塊在構造方法前執(zhí)行
    2024-11-11
  • elasticsearch中term與match的區(qū)別講解

    elasticsearch中term與match的區(qū)別講解

    今天小編就為大家分享一篇關于elasticsearch中term與match的區(qū)別講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • SpringBoot通過請求對象獲取輸入流無數(shù)據(jù)

    SpringBoot通過請求對象獲取輸入流無數(shù)據(jù)

    這篇文章主要介紹了使用SpringBoot通過請求對象獲取輸入流無數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • java文件操作報錯:java.io.FileNotFoundException(拒絕訪問)問題

    java文件操作報錯:java.io.FileNotFoundException(拒絕訪問)問題

    在進行編程時,經(jīng)常會遇到因疏忽小細節(jié)而導致的錯誤,如忘記在路徑后添加文件名,本文通過一個具體的修改前后對比示例,解釋了錯誤原因,并給出了解決方案,這類經(jīng)驗分享對編程學習者具有參考價值
    2024-10-10
  • 淺談java對象之間相互轉(zhuǎn)化的多種方式

    淺談java對象之間相互轉(zhuǎn)化的多種方式

    這篇文章主要介紹了淺談java對象之間相互轉(zhuǎn)化的多種方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • java實現(xiàn)ReadWriteLock讀寫鎖的示例

    java實現(xiàn)ReadWriteLock讀寫鎖的示例

    ReadWriteLock是Java并發(fā)包中的接口,定義了讀鎖和寫鎖,讀鎖允許多線程同時訪問共享資源,而寫鎖則要求獨占,這種機制適用于讀多寫少的場景,可以提高并發(fā)效率同時保證數(shù)據(jù)一致性,本文就來詳細的介紹一下如何實現(xiàn),感興趣的可以了解一下
    2024-09-09

最新評論

南和县| 友谊县| 饶阳县| 哈尔滨市| 峨眉山市| 连山| 连平县| 万年县| 准格尔旗| 平舆县| 神池县| 长葛市| 永济市| 中西区| 柘城县| 竹北市| 项城市| 罗定市| 祁门县| 西安市| 济源市| 辽阳市| 新干县| 华容县| 象山县| 莱州市| 河曲县| 民乐县| 西宁市| 北海市| 益阳市| 东城区| 分宜县| 黄龙县| 剑河县| 津市市| 马边| 桂平市| 伽师县| 庐江县| 鲁甸县|