麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

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

處理Java程序中的內存漏洞

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

  java 程序中也有內存漏洞?當然有。與流行的觀念相反,在 Java 編程中,內存治理仍然是需要考慮的問題。在本文中,您將了解到什么會導致內存漏洞以及何時應該關注這些漏洞。您還有機會實踐一下在您自己的項目中解決漏洞問題。
  
  Java 程序中的內存漏洞是如何顯現出來的
  大多數程序員都知道,使用像 Java 這樣的編程語言的一大好處就是,他們不必再擔心內存的分配和釋放問題。您只須創建對象,當應用程序不再需要這些對象時,Java 會通過一種稱為“垃圾收集”的機制將這些對象刪除。這種處理意味著 Java 已經解決了困擾其他編程語言的煩人問題 -- 可怕的內存漏洞。是這樣的嗎?
  
  在深入討論之前,我們先回顧一下垃圾收集的工作方式。垃圾收集器的工作是發現應用程序不再需要的對象,并在這些對象不再被訪問或引用時將它們刪除。垃圾收集器從根節點(在 Java 應用程序的整個生存周期內始終存在的那些類)開始,遍歷被引用的所有節點進行清除。在它遍歷這些節點的同時,它跟蹤哪些對象當前正被引用著。任何類只要不再被引用,它就符合垃圾收集的條件。當刪除這些對象以后,就可將它們所占用的內存資源返回給 Java 虛擬機 (JVM)。
  
  所以的確是這樣,Java 代碼不要求程序員負責內存的治理和清除,它會自動對無用的對象執行垃圾收集。但是,要緊記的一點是 僅當一個對象不再被引用時才會被統計為無用的。圖 1 說明了這個概念。
  
 處理Java程序中的內存漏洞(圖一)

  
圖 1. 無用但仍被引用的對象

  
  上面說明了在 Java 應用程序執行期間具有不同生存周期的兩個類。類 A 首先被實例化,并會在很長一段時間或程序的整個生存期內存在。在某個時候,類 B 被創建,類 A 添加對這個新創建的類的一個引用。現在,我們假定類 B 是某個用戶界面小部件,它由用戶顯示甚至解除。假如沒有清除類 A 對 B 的引用,則即便不再需要類 B,并且即便在執行下一個垃圾收集周期以后,類 B 仍將存在并占用內存空間。
  
  何時應該關注內存漏洞?
  假如您的程序在執行一段時間以后發出 java.lang.OutOfMemoryError 錯誤,則內存漏洞肯定是一個重大嫌疑。除了這種明顯的情況之外,何時還應該關注內存漏洞呢?持完美主義觀點的程序員肯定會回答,應該查找并糾正 所有內存漏洞。但是,在得出這個結論之前,還有幾個方面需要考慮,包括程序的生存期和漏洞的大小。
  
  完全有這樣的可能,垃圾收集器在應用程序的生存期內可能始終不會運行。不能保證 JVM 何時以及是否會調用垃圾收集器 -- 即便程序顯式地調用 System.gc() 也是如此。通常,在當前的可用內存能夠滿足程序的內存需求時,JVM 不會自動運行垃圾收集器。當可用內存不能滿足需求時,JVM 將首先嘗試通過調用垃圾收集來釋放出更多的可用內存。假如這種嘗試仍然不能釋放足夠的資源,JVM 將從操作系統獲取更多的內存,直至達到答應的最大極限。
  
  例如,考慮一個小型 Java 應用程序,它顯示一些用于修改配置的簡單用戶界面元素,并且它有一個內存漏洞。很可能到應用程序關閉時也不會調用垃圾收集器,因為 JVM 很可能有足夠的內存來創建程序所需的全部對象,而此后可用內存則所剩無幾。因此,在這種情況下,即使某些“死”對象在程序執行時占用著內存,它實際上并沒有什么用途。
  
  假如正在開發的 Java 代碼要全天 24 小時在服務器上運行,則內存漏洞在此處的影響就比在我們的配置實用程序中的影響要大得多。在要長時間運行的某些代碼中,即使最小的漏洞也會導致 JVM 耗盡全部可用內存。
  
  在相反的情況下,即便程序的生存期較短,假如存在分配大量臨時對象(或者若干吞噬大量內存的對象)的任何 Java 代碼,而且當不再需要這些對象時也沒有取消對它們的引用,則仍然可能達到內存極限。
  
  最后一種情況是內存漏洞無關緊要。我們不應該認為 Java 內存漏洞像其他語言(如 C++)中的漏洞那樣危險,在那些語言中內存將丟失,且永遠不會被返回給操作系統。在 Java 應用程序中,我們使不需要的對象依附于操作系統為 JVM 所提供的內存資源。所以從理論上講,一旦關閉 Java 應用程序及其 JVM,所分配的全部內存將被返回給操作系統。
  
  確定應用程序是否有內存漏洞
  為了查看在 Windows NT 平臺上運行的某個 Java 應用程序是否有內存漏洞,您可能試圖在應用程序運行時觀察“任務治理器”中的內存設置。但是,在觀察了運行中的幾個 Java 應用程序以后,您會發現它們比本地應用程序占用的內存要多得多。我做過的一些 Java 項目要使用 10 到 20 MB 的系統內存才能啟動。而操作系統自帶的 Windows EXPlorer 程序只需 5 MB 左右的內存。
  
  在 Java 應用程序內存使用方面應注重的另一點是,這個典型程序在 IBM JDK 1.1.8 JVM 中運行時占用的系統內存越來越多。似乎直到為它分配非常多的物理內存以后它才開始向系統返回內存。這些情況是內存漏洞的征兆嗎?
  
  要理解其中的緣由,我們必須熟悉 JVM 如何將系統內存用作它的堆。當運行 java.exe 時,您使用一定的選項來控制垃圾收集堆的起始大小和最大大小(分別用 -ms 和 -mx 表示)。Sun JDK 1.1.8 的默認起始設置為 1 MB,默認最大設置為 16 MB。IBM JDK 1.1.8 的默認最大設置為系統總物理內存大小的一半。這些內存設置對 JVM 在用盡內存時所執行的操作有直接影響。JVM 可能繼續增大堆,而不等待一個垃圾收集周期的完成。
  
  這樣,為了查找并最終消除內存漏洞,我們需要使用比任務監視實用程序更好的工具。當您試圖調試內存漏洞時,內存調試程序(請參閱參考資源)可能派得上用場。這些程序通常會顯示堆中的對象數、每個對象的實例數和這些對象所占用的內存等信息。此外,它們也可能提供有用的視圖,這些視圖可以顯示每個對象的引用和引用者,以便您跟蹤內存漏洞的來源。
  
  下面我將說明我是如何用 Sitraka Software 的 JPRobedebugger 檢測和去除內存漏洞的,以使您對這些工具的部署方式以及成功去除漏洞所需的過程有所了解。
  
  內存漏洞的一個示例
  本例集中討論一個問題,我們部門當時正在開發一個商業發行版軟件,這是一個 Java JDK 1.1.8 應用程序,一個測試人員花了幾個小時研究這個程序才最終使這個問題顯現出來。這個 Java 應用程序的基本代碼和包是由幾個不同的開發小組在不同的時間開發的。我猜想,該應用程序中意外出現的內存漏洞是由那些沒有真正理解別人開發的代碼的程序員造成的。
  
  我們正在討論的 Java 代碼答應用戶為 Palm 個人數字助理創建應用程序,而不必編寫任何 Palm OS 本地代碼。通過使用圖形用戶界面,用戶可以創建窗體,向窗體中添加控件,然后連接這些控件的事件來創建 Palm 應用程序。測試人員發現,隨著不斷創建和刪除窗體和控件,這個 Java 應用程序最終會耗盡內存。開發人員沒有檢測到這個問題,因為他們的機器有更多的物理內存。
  
  為了研究這個問題,我用 JProbe 來確定什么地方出了差錯。盡管用了 JProbe 所提供的強大工具和內存快照,研究仍然是一個冗長乏味、不斷重復的過程,首先要確定出現內存漏洞的原因,然后修改代碼,最后還得檢驗結果。
  
  JProbe 提供幾個選項,用來控制調試期間實際記錄哪些信息。經過幾次試驗以后,我斷定獲取所需信息的最有效方法是,關閉性能數據收集,而將注重力集中在所捕捉的堆數據上。JProbe 提供了一個稱為 Runtime Heap Summary 的視圖,它顯示 Java 應用程序運行時所占用的堆內存量隨時間的變化。它還提供了一個工具欄按鈕,必要時可以強制 JVM 執行垃圾收集。假如您試圖弄清楚,當 Java 應用程序不再需要給定的類實例時,這個實例會不會被作為垃圾收集,這個功能將很有用。圖 2 顯示了使用中的堆存儲量隨時間的變化。
  
 處理Java程序中的內存漏洞(圖二)

  
圖 2. Runtime Heap Summary

  
  在 Heap Usage Chart 中,藍色部分表明已分配的堆空間大小。在啟動這個 Java 程序并達到穩定狀態以后,我強制垃圾收集器運行,在圖中的表現就是綠線(這條線表明插入了一個檢查點)左側的藍線的驟降。隨后,我添加了四個窗體,然后又將它們刪除,并再次調用了垃圾收集器。當程序返回僅有一個可視窗體的初始狀態時,檢查點之后的藍色區域高于檢查點之前的藍色區域這一情況表明可能存在內存漏洞。我通過查看 Instance Summary 證實確實有一個漏洞,因為 Instance Summary 表明 FormFrame 類(它是窗體的主用戶界面類)的計數在檢查點之后增加了 4。
  
  查找原因
  為了將測試人員報告的問題剔出,我采取的第一個步驟是找出幾個簡單的、可重復的測試案例。就本例而言,我發現只須添加一個窗體,將它刪除,然后強制執行垃圾收集,結果就會導致與被刪除窗體相關聯的許多類實例仍然處于活動狀態。這個問題在 JProbe 的 Instance Summary 視圖中很明顯,這個視圖統計每個 Java 類在堆中的實例數。
  
  為了查明使垃圾收集器無法正常完成其工作的那些引用,我使用 JProbe 的 Reference Graph(如圖 3 所示)來確定哪些類仍然引用著目前未被刪除的 FormFrame 類。在調試這個問題時該過程是最復雜的過程之一,因為我發現許多不同的對象仍然引用著這個無用的對象。用來查明究竟是哪個引用者真正造成這個問題的試錯過程相當耗時。
  
  在本例中,一個根類(左上角用紅色標明的那個類)是問題的發源地。右側用藍色突出顯示的類處在從最初的 FormFrame 類跟蹤而來的路徑上。
  
處理Java程序中的內存漏洞(圖三)

  
圖 3. 在引

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 九九热免费精品 | 日日鲁夜夜视频热线播放 | 成人在线视频在线观看 | lutube成人福利在线观看 | 国产黄色免费网站 | 日韩电影一区二区三区 | 97视频| 亚洲精品在线观看网站 | 深夜激情视频 | 大学生一级毛片在线视频 | 精品国产一区二区三区四区在线 | 色吧久久 | 久久国产免费 | 久久精品国产99久久6动漫亮点 | 国产在线1区 | 天天夜碰日日摸日日澡性色av | 国产亚色 | 亚洲视屏在线观看 | 免费在线观看成人av | 国产精品视频一区二区三区综合 | hd极品free性xxx一护士 | 久草在线手机视频 | 水多视频在线观看 | 国产美女视频一区 | 日本高清com| 天天黄色片 | 成年人黄视频 | 免费一级欧美在线观看视频 | 国人精品视频在线观看 | 蜜桃91麻豆| 欧美a∨一区二区三区久久黄 | 国产免费久久久久 | 欧美成人一区二区视频 | 亚洲成人午夜精品 | 午夜男人在线观看 | 欧美一级免费高清 | 成人免费久久网 | 国产日韩在线视频 | 青青草最新网址 | 成人免费午夜视频 | 欧洲色阁中文字幕 |