亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

對象引用是怎樣嚴重影響垃圾收集器

2019-11-18 11:58:58
字體:
來源:轉載
供稿:網友

  假如您認為 java 游戲開發人員是 Java 編程世界的一級方程式賽車手,那么您就會明白為什么他們會如此地重視程序的性能。 游戲開發人員幾乎天天都要面對的性能問題,往往超過了一般程序員考慮問題的范圍。哪里可以找到這些非凡的開發人員呢?Java 游戲社區就是一個好去處(參見 參考資料)。 雖然在這個站點可能沒有很多關于服務器端的應用,但是我們依然可以從中受益,看看這些“惜比特如金”的游戲開發人員天天所面對的,我們往往能從中得到寶貴的經驗。讓我們開始游戲吧!
  
  對象泄漏
  
  游戲程序員跟其他程序員一樣??他們也需要理解 Java 運行時環境的一些微妙之處,比如垃圾收集。垃圾收集可能是使您感到難于理解的較難的概念之一, 因為它并不能總是毫無遺漏地解決 Java 運行時環境中堆治理的問題。似乎有很多類似這樣的討論,它的開頭或結尾寫著:“我的問題是關于垃圾收集”。
  
  假如您正面遭遇內存耗盡(out-of-memory)的錯誤。于是您使用檢測工具想要找到問題所在,但這是徒勞的。您很輕易想到另外一個比較可信的原因:這是 Java 虛擬機堆治理的問題,而不會認為這是您自己的程序的緣故。但是,正如 Java 游戲社區的資深專家不止一次地解釋的,Java 虛擬機并不存在任何被證實的對象泄漏問題。實踐證實,垃圾收集器一般能夠精確地判定哪些對象可被收集,并且重新收回它們的內存空間給 Java 虛擬機。所以,假如您碰到了內存耗盡的錯誤,那么這完全可能是由您的程序造成的,也就是說您的程序中存在著“無意識的對象保留(unintentional object retention)”。
  
  內存泄漏與無意識的對象保留
  
  內存泄漏和無意識的對象保留的區別是什么呢?對于用 Java 語言編寫的程序來說,確實沒有區別。兩者都是指在您的程序中存在一些對象引用,但實際上您并不需要引用這些對象。一個典型的例子是向一個集合中加入一些對象以便以后使用它們,但是您卻忘了在使用完以后從集合中刪除這些對象。因為集合可以無限制地擴大,并且從來不會變小,所以當您在集合中加入了太多的對象(或者是有很多的對象被集合中的元素所引用)時,您就會因為堆的空間被填滿而導致內存耗盡的錯誤。垃圾收集器不能收集這些您認為已經用完的對象,因為對于垃圾收集器來說,應用程序仍然可以通過這個集合在任何時候訪問這些對象,所以這些對象是不可能被當作垃圾的。
  
  對于沒有垃圾收集的語言來說,例如 C++ ,內存泄漏和無意識的對象保留是有區別的。C++ 程序跟 Java 程序一樣,可能產生無意識的對象保留。但是 C++ 程序中存在真正的內存泄漏,即應用程序無法訪問一些對象以至于被這些對象使用的內存無法釋放且返還給系統。令人欣慰的是,在 Java 程序中,這種內存泄漏是不可能出現的。所以,我們更喜歡用“無意識的對象保留”來表示這個令 Java 程序員抓破頭皮的內存問題。這樣,我們就能區別于其他使用沒有垃圾收集語言的程序員。
  
  跟蹤被保留的對象
  
  那么當發現了無意識的對象保留該怎么辦呢?首先,需要確定哪些對象是被無意保留的,并且需要找到究竟是哪些對象在引用它們。然后必須安排好 應該在哪里釋放它們。最輕易的方法是使用能夠對堆產生快照的檢測工具來標識這些對象,比較堆的快照中對象的數目,跟蹤這些對象,找到引用這些對象的對象,然后強制進行垃圾收集。有了這樣一個檢測器,接下來的工作相對而言就比較簡單了:
  
  等待直到系統達到一個穩定的狀態,這個狀態下大多數新產生的對象都是暫時的,符合被收集的條件;這種狀態一般在程序所有的初始化工作都完成了之后。
  
  強制進行一次垃圾收集,并且對此時的堆做一份對象快照。
  
  進行任何可以產生無意地保留的對象的操作。
  
  再強制進行一次垃圾收集,然后對系統堆中的對象做第二次對象快照。
  
  比較兩次快照,看看哪些對象的被引用數量比第一次快照時增加了。因為您在快照之前強制進行了垃圾收集,那么剩下的對象都應該是被應用程序所引用的對象,并且通過比較兩次快照我們可以準確地找出那些被程序保留的、新產生的對象。
  
  根據您對應用程序本身的理解,并且根據對兩次快照的比較,判定出哪些對象是被無意保留的。
  
  跟蹤這些對象的引用鏈,找出究竟是哪些對象在引用這些無意地保留的對象,直到您找到了那個根對象,它就是產生問題的根源。
  
  顯式地賦空(nulling)變量
  
  一談到垃圾收集這個主題,總會涉及到這樣一個吸引人的討論,即顯式地賦空變量是否有助于程序的性能。賦空變量是指簡單地將 null 值顯式地賦值給這個變量,相對于讓該變量的引用失去其作用域。
  
  清單 1. 局部作用域
  
  public static String scopingExample(String string) {
  
  StringBuffer sb = new StringBuffer();
  
  sb.append("hello ").append(string);
  
  sb.append(", nice to see you!");
  
  return sb.toString();
  
  }
  
  當該方法執行時,運行時棧保留了一個對 StringBuffer 對象的引用,這個對象是在程序的第一行產生的。在這個方法的整個執行期間,棧保存的這個對象引用將會防止該對象被當作垃圾。當這個方法執行完畢,變量 sb 也就失去了它的作用域,相應地運行時棧就會刪除對該 StringBuffer 對象的引用。于是不再有對該 StringBuffer 對象的引用,現在它就可以被當作垃圾收集了。棧刪除引用的操作就等于在該方法結束時將 null 值賦給變量 sb。
  
  錯誤的作用域
  
  既然 Java 虛擬機可以執行等價于賦空的操作,那么顯式地賦空變量還有什么用呢?對于在正確的作用域中的變量來說,顯式地賦空變量的確沒用。但是讓我們來看看另外一個版本的 scopingExample 方法,這一次我們將把變量 sb 放在一個錯誤的作用域中。
  
  清單 2. 靜態作用域
  
  static StringBuffer sb = new StringBuffer();
  
  public static String scopingExample(String string) {
  
  sb = new StringBuffer();
  
  sb.append("hello ").append(string);
  
  sb.append(", nice to see you!");
  
  return sb.toString();
  
  }
  
  現在 sb 是一個靜態變量,所以只要它所在的類還裝載在 Java 虛擬機中,它也將一直存在。該方法執行一次,一個新的 StringBuffer 將被創建并且被 sb 變量引用。在這種情況下,sb 變量以前引用的 StringBuffer 對象將會死亡,成為垃圾收集的對象。也就是說,這個死亡的 StringBuffer 對象被程序保留的時間比它實際需要保留的時間長得多??假如再也沒有對該 scopingExample 方法的調用,它將會永遠保留下去。
  
  一個有問題的例子
  
  即使如此,顯式地賦空變量能夠提高性能嗎?我們會發現我們很難相信一個對象會或多或少對程序的性能產生很大影響,直到我看到了一個在 Java Games 的 Sun 工程師給出的一個例子,這個例子包含了一個不幸的大型對象。
  
  清單 3. 仍在靜態作用域中的對象
  
  PRivate static Object bigObject;
  
  public static void test(int size) {
  
  long startTime = System.currentTimeMillis();
  
  long numObjects = 0;
  
  while (true) {
  
  //bigObject = null; //eXPlicit nulling
  
  //SizableObject could simply be a large array, e.g. byte[]
  
  //In the JavaGaming discussion it was a BufferedImage
  
  bigObject = new SizableObject(size);
  
  long endTime = System.currentTimeMillis();
  
  ++numObjects;
  
  // We print stats for every two seconds
  
  if (endTime - startTime >= 2000) {
  
  System.out.println("Objects created per 2 seconds = " + numObjects);
  
  startTime = endTime;
  
  numObjects = 0;
  
  }
  
  }
  
  }
  
  這個例子有個簡單的循環,創建一個大型對象并且將它賦給同一個變量,每隔兩秒鐘報告一次所創建的對象個數?,F在的 Java 虛擬機采用 generational 垃圾收集機制,新的對象創建之后放在一個內存空間(取名 Eden)內,然后將那些在第一次垃圾收集以后仍然保留的對象轉移到另外一個內存空間。在 Eden,即創建新對象時所在的新一代空間中,收集對象要比在“老一代”空間中快得多。但是假如 Eden 空間已經滿了,沒有空間可供分配,那么就必須把 Eden 中的對象轉移到老一代空間中,騰出空間來給新創建的對象。假如沒有顯式地賦空變量,而且所創建的對象足夠大,那么 Eden 就會填滿,并且垃圾收集器就不能收集當前所引用的這個大型對象。所產生的后果是,這個大型對象被轉移到“老一代空間”,并且要花更多的時間來收集它。
  
  通過顯式地賦空變量,Eden 就能在新對象創建之前獲得自由空間,這樣垃圾收集就會更快。實際上,在顯式賦空的情況下,該循環在兩秒鐘內創建的對象個數是沒有顯式賦空時的5倍??但是僅當您選擇創建的對象要足夠大而可以填滿 Eden 時才是如此, 在 Windows 環境、Java虛擬機 1.4 的默認配置下大概需要 500KB。那就是一行賦空操作產生的 5 倍的性能差距。但是請注重這個性能差別產生的原因是變量的作用域不正確,這正是賦空操作發揮作用的地方,并且是因為所創建的對象非常大。
  
  最佳實踐
  
  這是一個有趣的例子,但是值得強調的是,

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美xxxx做受欧美| 欧美理论电影在线播放| 精品亚洲一区二区三区在线播放| 精品在线观看国产| 91国产美女在线观看| 亚洲精品丝袜日韩| 国产亚洲精品一区二555| 国产一区二区三区在线观看网站| 久99九色视频在线观看| 国产欧美一区二区三区在线看| 九九视频这里只有精品| 九九久久久久久久久激情| 欧美激情一二三| 久久精品国产99国产精品澳门| 日韩电影免费在线观看| 亚洲精品短视频| 亚洲成人精品视频| 国产女人18毛片水18精品| 国产精品电影在线观看| 亚洲黄色在线观看| 97视频网站入口| 日韩欧美成人网| 91av在线看| 久久精品中文字幕| 国产成人涩涩涩视频在线观看| 欧美黑人巨大xxx极品| 最近2019免费中文字幕视频三| 国产欧美韩国高清| 国产免费一区二区三区在线能观看| 欧美激情videoshd| 亚洲国产97在线精品一区| 欧美成人精品在线视频| 欧美天天综合色影久久精品| 午夜精品久久久久久久99热浪潮| 欧美日韩国产一区在线| 久久视频中文字幕| 欧洲亚洲免费视频| www.亚洲天堂| 91精品国产自产在线观看永久| 国产精品视频免费在线观看| 中文字幕欧美视频在线| 69影院欧美专区视频| 日韩视频免费观看| 国产成人精品一区二区| 中文字幕不卡在线视频极品| 日韩精品中文在线观看| 亚洲欧洲国产伦综合| 国产精品中文久久久久久久| 久久久久久18| 欧美在线视频一区| 国产精品在线看| 欧美第一黄色网| 中文字幕日韩免费视频| 亚洲欧美精品伊人久久| 国外成人性视频| 亚洲精品一区久久久久久| 国产精品免费视频久久久| 日韩中文字幕视频在线观看| 国产精品久久二区| 国产999精品久久久| 国产一区私人高清影院| 久久久久久久久久国产| 欧美美女操人视频| 这里只有精品在线播放| 九九热精品视频国产| 久久精品夜夜夜夜夜久久| 成人a在线观看| 久久在线视频在线| 日韩精品在线观看视频| 中文字幕成人在线| 欧美在线免费视频| 精品福利视频导航| 成人黄色生活片| 日韩中文在线观看| 欧美性开放视频| 国产欧美婷婷中文| 精品久久国产精品| 夜夜嗨av色综合久久久综合网| 国产在线精品成人一区二区三区| 成人精品网站在线观看| 这里只有精品在线观看| 91麻豆国产语对白在线观看| 亚洲免费伊人电影在线观看av| 亚洲第五色综合网| 国产日韩在线亚洲字幕中文| 久久69精品久久久久久国产越南| 久久久久久久久久国产精品| 亚洲黄色www网站| 91性高湖久久久久久久久_久久99| 在线观看日韩专区| 在线免费观看羞羞视频一区二区| 国产精品三级美女白浆呻吟| 一本色道久久88亚洲综合88| 精品国产乱码久久久久久虫虫漫画| 亚洲第一区在线观看| 国产在线拍偷自揄拍精品| 亚洲欧洲国产一区| 精品久久久久久久久中文字幕| 精品偷拍各种wc美女嘘嘘| 日韩av网站大全| xvideos亚洲人网站| 日韩欧美视频一区二区三区| 国产精品网站视频| 亚洲国产精品视频在线观看| 欧美日韩激情视频8区| 国产精品久久久久久久久久小说| 国产不卡av在线免费观看| 日韩欧亚中文在线| 97在线看福利| 日韩最新av在线| 欧美与欧洲交xxxx免费观看| 日韩精品免费综合视频在线播放| 国产精品精品视频| 精品福利视频导航| 欧美一区二区影院| 日韩精品在线私人| 91网站在线免费观看| 日韩一区二区三区xxxx| 奇米4444一区二区三区| 国产成人精品在线视频| 国产精品自产拍在线观看中文| 国产精品极品美女粉嫩高清在线| 亚洲欧美在线免费观看| 97香蕉久久超级碰碰高清版| 国产91精品在线播放| 国产精品入口日韩视频大尺度| 在线免费观看羞羞视频一区二区| 日韩女优人人人人射在线视频| 国产精品一区二区三区成人| 亚洲男人天堂手机在线| 久久精品国产视频| 欧美激情性做爰免费视频| 日本精品va在线观看| 亚洲自拍高清视频网站| 精品一区二区电影| 久久久久成人网| 国产精品久久久久久久久久免费| 久久久午夜视频| 成人黄色av免费在线观看| 亚洲人成77777在线观看网| 疯狂做受xxxx欧美肥白少妇| 日韩欧美亚洲国产一区| 欧美日韩中文在线| 日韩麻豆第一页| 欧美韩国理论所午夜片917电影| 久久五月天综合| 亚洲人成在线播放| 中文字幕亚洲自拍| 国产99久久精品一区二区 夜夜躁日日躁| 久久天天躁夜夜躁狠狠躁2022| 57pao国产成人免费| 久久999免费视频| 国产精品主播视频| 中文字幕日韩av综合精品| 欧美日韩国产综合视频在线观看中文| 欧美日韩精品中文字幕| 亚洲精品国产精品国产自| 国产精品久久久久9999| 亚洲黄色有码视频| 亚洲一区二区三区xxx视频| 国产在线视频一区| 精品国偷自产在线视频99| 欧美自拍视频在线观看| 欧美日本高清一区|