国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 理解Java垃圾回收

理解Java垃圾回收

2020-04-13 11:31趙杰A-124 JAVA教程

這篇文章主要幫助大家理解Java垃圾回收,通過實例學習java垃圾回收,什么是垃圾回收,感興趣的小伙伴們可以參考一下

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

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

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

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

示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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通常有三種常見的情況,這三種情況通常都不易發現,短時間內運行也不會有什么問題,但是時間久了后,泄漏的對象增加后終會引起程序崩潰。

類自己管理內存時,要警惕內存泄漏
示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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();
  }
 }
 
}

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

elements[size] = null;即可。

緩存是要警惕內存泄漏
出現這樣情況通常是一旦將對象放入緩存,很可能長時間不使用很容易遺忘,通常可以用WakeHashMap代表緩存,在緩存中的項過期后,他們可以被自動刪除。或者可以由一個后臺線程定期執行來清除緩沖中的過期項。

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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();
 }
 
}

執行結果:

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

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

如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
或者

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
  }
 
}

執行結果:

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Parent2{
  private final Object finalizeGuardian = new Object() {
    protected void finalize() throws Throwable {
      System.out.println("在此執行父類終結方法中的邏輯");
    };
  };
}
 
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();
  }
 
}

執行結果:

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产亚洲成av人片在线观看桃 | 毛片久久久| 日日操夜 | 国产成年人在线观看 | 九九久久国产 | aaa欧美大片 | 中文字幕一区二区三区精彩视频 | 国产成人综合视频 | 国产一区日韩精品 | 黑人巨大精品欧美一区免费视频 | 久久国| 日韩在线视频免费观看 | 亚洲色图网站 | 国产伦精品一区二区三区四区视频 | 亚洲国产高清在线 | 中文字幕在线观看一区二区三区 | 伊人色综合网 | 中文字幕精品一区 | 一区自拍 | 亚洲一区 欧美 | 国产目拍亚洲精品99久久精品 | 日韩一区二区三区在线视频 | 激情毛片| 国产成人精品一区二区三区视频 | 视频一区二区国产 | 一区二区三区欧美 | 欧美中文字幕一区二区三区 | 韩日在线观看视频 | youjizz国产 | 国产精品精品 | 亚洲精品一区二区三区蜜桃久 | 国精品一区二区三区 | 日本高清一区 | 午夜播影院 | 快色视频在线观看 | 欧美精品久久 | 国产欧美精品一区二区色综合 | 国产精品日产欧美久久久久 | 久久国产亚洲视频 | 中文字幕免费在线 | 精品久久久久久久久久久 |