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

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

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java內存管理關系及內存泄露的原理分析

java內存管理關系及內存泄露的原理分析

2022-02-15 16:00知我飯否 Java教程

這篇文章主要介紹了java內存管理關系及內存泄露的原理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

java內存管理關系及內存泄露原理

這可能是最近寫的博客中最接近底層的了。閑言少敘,進入正題。

java對象和內存的關系

首先,我們要知道下面幾條真理(自己總結的)

  • 一個完整的建立對象流程是 1聲明對象,2開辟內存空間,3將對象和內存空間建立聯(lián)系。
  • 一個對象只能對應一個內存空間,一個內存空間可以對應很多對象
  • 回收一個內存空間 。如果,這個內存空間沒有任何一個對象和他有聯(lián)系。就可以被回收,或者好幾個對象環(huán)形引用,也會被回收
  • 對一個對象進行操作的時候,是先通過 對象 找到 內存空間,然后 對內存空間進行操作(讀,寫 改 刪)

這是本人總結出來的四條經(jīng)驗。

特別重要的是,一定要有這種認知。不管任何語言,最終都是要物理內存上面反映的,對象 和 內存空間 是兩個不同的個體。 如果 沒有的話,那么你會發(fā)現(xiàn) 下面將的都是什么啊!

創(chuàng)建對象

     Stu one; //只聲明 one對象 但是沒有分配內存空間
      //用new 開辟新的內存空間 oneMemory ,調用構造函數(shù)賦值,并將內存空間 oneMemory 與 one對象建立聯(lián)系。
      one = new Stu("one");
      
      //聲明 two對象 并開辟內存 twoMemory 調用構造函數(shù)賦值,并將內存空間 twoMemory與 two對象建立聯(lián)系
      Stu two = new Stu("two");
      
      //聲明 three對象, 并找到one 對象聯(lián)系的內存空間 oneMemory。并將 oneMemory與 three 對象建立聯(lián)系
      Stu three = one;
      
      //此時 內存空間 oneMemory 與兩個對象有聯(lián)系。一個是 one對象,一個是three對象
      System.out.println("three 和 one 是否相等" + (three == one) + " one的哈希值" + one.hashCode() + " three的哈希值" + three.hashCode());

運行結果

java內存管理關系及內存泄露的原理分析

我們可以發(fā)現(xiàn),three對象 和one對象 指向的是同一個內存空間oneMemory。這個不就是符合上面所說的第二個真理 如果,我們對one對象進行操作,那么產(chǎn)生的影響,也會反映到three對象上。

因為,**他們指向的是同一個內存空間,對one對象操作,就是做內存空間oneMemory進行操作。而three對象指向的也是oneMemory。這個符合上面第四條真理。**例子如下

      System.out.println("three 對象的值" + three.getName() + three.hashCode());
      //修改one的值,第一步 找到one對象聯(lián)系的內存空間 oneMemory , 將內存空間oneMemory 中的name值改變
      one.setName("change");
      //讀取three對象值時候,先找到three對象聯(lián)系的內存空間oneMemory,讀取其中的name值
      System.out.println("three 對象的值" + three.getName() + three.hashCode());

null的作用

長久以來,我只知道,將一個值復制成null,那么他就是空的了。但是 完全不知道,為啥。

還是接著上面的例子,看一段代碼;

       //讀取three對象值時候,先找到three對象聯(lián)系的內存空間oneMemory,讀取其中的name值
      System.out.println("three 對象的值 before" + three.getName() + three.hashCode());
      /*
       此時 如果 我們把one 對象 設置為null的。 對內存空間 oneMemory 是沒有影響的
       =null的作用是 將one對象自己本身 對內存空間的聯(lián)系去除,并不會影響到內存空間和其他對象的聯(lián)系
       */
      one = null;
      System.out.println("three 對象的值  after" + three.getName() + three.hashCode());

運行結果

java內存管理關系及內存泄露的原理分析

我們會發(fā)現(xiàn) 將one對象賦值為空后,three對象還是和先前一樣。以前一直認為null,是將對象和他的內存空間清楚。但現(xiàn)在不是!。代碼注釋里面寫的很清楚了。null 并不是清除內存空間,他只是把對象自己本身和內存空間的聯(lián)系切斷了

內存泄露

如果,你明白了上面。那么內存泄露對你來說也很簡單了。

再來學習一個新概念

java內存管理關系及內存泄露的原理分析

上面這么多呢。在本篇文章里面,你只需要記住 被static關鍵詞修飾的變量,類,方法的生命周期是伴隨整個程序的。就是程序活多久,他們就活多久

接下來看代碼

首先,我們定義一個靜態(tài)集合 staticList ,他是程序一運行,就會被創(chuàng)建好的。程序結束運行了,它才會被回收。

static List<Stu> staticList = new ArrayList<>();//開辟內存空間 listMemory
     System.out.println("three 對象的值  after" + three.getName() + three.hashCode());
      /*
       內存泄露 是長生命周期的對象 對一個內存空間有聯(lián)系,造成內存空間沒有辦法被回收
       */
      /*
      將three對象添加到靜態(tài)集合里面,步驟是這樣的,
      第一步 找到three對象聯(lián)系的內存空間 oneMemory
      第二步 找到 staticList集合對象聯(lián)系的內存空間 listMemory
      第三步 告訴系統(tǒng) staticList集合對象的部分成員 和內存空間 oneMemory 建立聯(lián)系。
       */
      staticList.add(three);
      
      /*
      在這里 即使three對象已經(jīng)和內存空間 oneMemory 沒有聯(lián)系了。
      oneMemory 也不會被回收,因為上面說了內存空間和對象的關系是1對多。
       而回收的條件是 一個內存空間沒有一條和對象的聯(lián)系才可以回收。
       此時 內存空間 和staticList集合對象的部分成員 有聯(lián)系,所以 內存空間不會被回收。
       又由于staticList 集合對象聯(lián)系的內存空間在 靜態(tài)存儲區(qū),是伴隨整個程序的。所以 在整個程序生命里面,
       內存空間 oneMemory  就得不到 回收。  就是內存泄露了。
       */
      three = null;
      System.out.println(staticList.get(0).hashCode());

運行結果

java內存管理關系及內存泄露的原理分析

可以看見。在我們將three對象賦值null切斷和內存空間 oneMemory的聯(lián)系后。靜態(tài)集合staticList對象的部分成員依然和內存空間 oneMemory有聯(lián)系。根據(jù)上面第三條所說,因為內存空間 oneMemory 還是和對象有聯(lián)系的(staticList)。所以不會回收oneMemory內存空間。又由于staticList是靜態(tài)的,生命和程序一樣長。 那么在整個程序周期里面,oneMemory內存空間 都不會被回收。就造成了內存泄露。

附上完整的代碼

package com.zfh.test;
import java.util.ArrayList;
import java.util.List;
public class JavaMain {
  static List<Stu> staticList = new ArrayList<>();//開辟內存空間 listMemory
  public static void main(String[] args) {
      Stu one; //只聲明 one對象 但是沒有分配內存空間
      //用new 開辟新的內存空間 oneMemory ,調用構造函數(shù)賦值,并將內存空間 oneMemory 與 one對象建立聯(lián)系。
      one = new Stu("one");
      //聲明 two對象 并開辟內存 twoMemory 調用構造函數(shù)賦值,并將內存空間 twoMemory與 two對象建立聯(lián)系
      Stu two = new Stu("two");
      //聲明 three對象, 并找到one 對象聯(lián)系的內存空間 oneMemory。并將 oneMemory與 three 對象建立聯(lián)系
      Stu three = one;
      //此時 內存空間 oneMemory 與兩個對象有聯(lián)系。一個是 one對象,一個是three對象
      System.out.println("three 和 one 是否相等" + (three == one) + " one的哈希值" + one.hashCode() + " three的哈希值" + three.hashCode());
      System.out.println("three 對象的值" + three.getName() + three.hashCode());
      //修改one的值,第一步 找到one對象聯(lián)系的內存空間 oneMemory , 將內存空間oneMemory 中的name值改變
      one.setName("change");
      //讀取three對象值時候,先找到three對象聯(lián)系的內存空間oneMemory,讀取其中的name值
      System.out.println("three 對象的值 before" + three.getName() + three.hashCode());
      /*
       此時 如果 我們把one 對象 設置為null的。 對內存空間 oneMemory 是沒有影響的
       =null的作用是 將one對象自己本身 對內存空間的聯(lián)系去除,并不會影響到內存空間和其他對象的聯(lián)系
       */
      one = null;
      System.out.println("three 對象的值  after" + three.getName() + three.hashCode());
      /*
       內存泄露 是長生命周期的對象 對一個內存空間有聯(lián)系,造成內存空間沒有辦法被回收
       */
      /*
      將three對象添加到靜態(tài)集合里面,步驟是這樣的,
      第一步 找到three對象聯(lián)系的內存空間 oneMemory
      第二步 找到 staticList集合對象聯(lián)系的內存空間 listMemory
      第三步 告訴系統(tǒng) staticList集合對象的部分成員 和內存空間 oneMemory 建立聯(lián)系。
       */
      staticList.add(three);
      /*
      在這里 即使three對象已經(jīng)和內存空間 oneMemory 沒有聯(lián)系了。
      oneMemory 也不會被回收,因為上面說了內存空間和對象的關系是1對多。
       而回收的條件是 一個內存空間沒有一條和對象的聯(lián)系才可以回收。
       此時 內存空間 和staticList集合對象的部分成員 有聯(lián)系,所以 內存空間不會被回收。
       又由于staticList 集合對象聯(lián)系的內存空間在 靜態(tài)存儲區(qū),是伴隨整個程序的。所以 在整個程序生命里面,
       內存空間 oneMemory  就得不到 回收。  就是內存泄露了。
       */
      three = null;
      System.out.println(staticList.get(0).hashCode());
  }
}

bean對象 即Stu

package com.zfh.test;
public class Stu {
/*  static {
      System.out.println("靜態(tài)代碼塊 我只調用一次");
  }*/

  private String name;
  
/*  {
      System.out.println("構造代碼塊");
  }*/

  public Stu(String name) {
      this.name = name;
  }
  public String getName() {
      return name;
  }
  public void setName(String name) {
      this.name = name;
  }
  public void sout(){
      System.out.println(this.name+this.hashCode());
  }
  public void printer() {
      System.out.println(Stu.class.hashCode());
  }
  @Override
  protected void finalize() throws Throwable {
      super.finalize();
      System.out.println("終結了");
  }
}

 

檢測內存泄露的原理

檢測內存泄漏的關鍵是要能截獲住對分配內存和釋放內存的函數(shù)的調用。截獲住這兩個函數(shù),我們就能跟蹤每一塊內存的生命周期,比如,每當成功的分配一塊內存后,就把它的指針加入一個全局的list中;每當釋放一塊內存,再把它的指針從list中刪除。這樣,當程序結束的時候,list中剩余的指針就是指向那些沒有被釋放的內存。這里只是簡單的描述了檢測內存泄漏的基本原理,詳細的算法可以參見Steve Maguire的<<Writing Solid Code>>。  

如果要檢測堆內存的泄漏,那么需要截獲住malloc/realloc/free和new/delete就可以了(其實new/delete最終也是用malloc/free的,所以只要截獲前面一組即可)。對于其他的泄漏,可以采用類似的方法,截獲住相應的分配和釋放函數(shù)。比如,要檢測BSTR的泄漏,就需要截獲SysAllocString/SysFreeString;要檢測HMENU的泄漏,就需要截獲CreateMenu/ DestroyMenu。(有的資源的分配函數(shù)有多個,釋放函數(shù)只有一個,比如,SysAllocStringLen也可以用來分配BSTR,這時就需要截獲多個分配函數(shù))。

在Windows平臺下,檢測內存泄漏的工具常用的一般有三種,MS C-Runtime Library內建的檢測功能;外掛式的檢測工具,諸如,Purify,BoundsChecker等;利用Windows NT自帶的Performance Monitor。這三種工具各有優(yōu)缺點,MS C-Runtime Library雖然功能上較之外掛式的工具要弱,但是它是免費的;Performance Monitor雖然無法標示出發(fā)生問題的代碼,但是它能檢測出隱式的內存泄漏的存在,這是其他兩類工具無能為力的地方。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/a1064072510/article/details/83148538

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 午夜av一区二区 | 精品一二区 | 亚洲永久免费 | 国产精品毛片一区视频播不卡 | 日韩成人精品在线 | 中国妞xxx| 在线一区观看 | 国产在线91| 国产在线在线 | 亚洲一区二区在线 | 亚洲专区国产精品 | 久久久99精品免费观看 | 91在线精品一区二区三区 | 国产毛片毛片 | 日韩黄网站 | 国产精品久久久久久久久久免费动 | 亚洲电影一区二区三区 | 亚洲久草 | 国产黄色在线播放 | 另类久久 | 99精品视频在线 | 久久综合av | 高清视频一区二区三区 | 欧美中文字幕一区二区三区亚洲 | 韩日一区二区 | 亚洲国产精品一区久久av篠田 | 久久久成人精品 | 国产精品久久久久久久久久久久| 日韩精品一区二区在线观看 | 国产精品国产 | 一级黄色毛片免费观看 | 欧美综合一区 | 国产一区二区三区在线免费观看 | 久久综合久久综合久久 | 日本不卡高字幕在线2019 | 日韩精品一区二区三区第95 | 久久久久久久久久久亚洲 | 亚洲精品粉嫩美女一区 | 日韩三级在线免费观看 | 中文在线视频 | 超碰中文字幕 |