1. 程式人生 > >淺談java的記憶體分配問題

淺談java的記憶體分配問題

記憶體

記憶體大家都知道(當然不是硬碟啊)。與c、c++相比呢,Java在記憶體管理的方面一個優越之處就是我們不用顯式的去對物件進行記憶體的分配和記憶體的回收,可能有人會著迷於對記憶體使用分配的這種快感,但是隨著程式變大,對於記憶體的維護工作也就越來越大。Java的JVM的自動記憶體管理機制,凸顯出了強大的優越感。。。。

但反而是因為這樣的一個現狀,就弱化了我們在寫Java程式時遇到記憶體溢位等問題時的定位能力和解決問題的能力。就在這個時候一本書應運而生--- 《深入理解java虛擬機器》 這本書也算是我旁邊落灰最嚴重的一本了,但寫程式就是這樣如果不沉到底,程式浮於表面那就只是單純的應用,不能變的熟練。
只有我們真正的瞭解了JVM如何管理記憶體後,才能遇見OutOfMemory錯誤時,快速的根據異常日誌資訊定位和解決問題。

Java記憶體分配方式

Java記憶體分配方式

咱們看看上面這張圖,顏色這麼鮮豔,這次一定能記住了!

  1. 靜態 儲存區

    記憶體在程式編譯的時候就已經分配好了,這塊記憶體在程式的整個執行期間都存在。比如,static 、全域性變數
  2. 在  上建立

    在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分匹配運算內置於處理器的指令集中、效率很高、但是分配的記憶體容量非常有限。
  3. 在  上分配

    動態記憶體分配。在c和c++中執行程式時用 malloc 或 new申請任意大小的記憶體,我們需要自己決定自己在何時何地使用使用free和delete來釋放記憶體。

Java虛擬機器記憶體模型是Java程式執行的基礎。虛擬機器在執行Java程式的過程中會把他所管理的記憶體劃分為若干的不同的資料區域,ok,這裡加重 是分為不同的資料區域

,這些區域都有自己的用途以及建立和銷燬的時間。看一下下圖,

太好了,又畫了一個帶顏色的圖~那就說一說為什麼帶不同的顏色吧

  • 紫色,由所有執行緒共享的資料區
  • 執行緒隔離的資料區

程式計數器

暫存器裡面有一個叫指令暫存器,用來儲存現在正在被執行的指令。想象一下,在JVM中怎麼辦,程式暫存器就是這樣的功能。

程式技術器是一塊較小的記憶體空間,它可以看做是當前執行緒所執行的位元組碼的行號指示器。“位元組碼”就是Java程式被編譯之後的形態,JVM有位元組碼直譯器,這個直譯器要解釋程式的哪段,就由這個程式技術器來決定的。

Java虛擬機器棧

Java虛擬機器棧也是執行緒私有的,生命週期與執行緒相同,虛擬機器棧描述的是Java方法執行的記憶體模型。每個方法在執行的同時會建立棧幀,儲存

  • 區域性變量表
  • 運算元棧
  • 動態連結
  • 方法出口
    每個方法從呼叫直到執行完成的過程,就對應整一個棧幀在虛擬機器棧中入棧和出棧的過程。
    平時咱們在討論的時候總會提到“棧”和“堆”這兩種記憶體區域,那麼其中的棧,就是這裡所指的棧,更細一點說,就是虛擬機器棧中區域性變數的部分。

在換一個方面講解一下,虛擬機器棧是用來被快速訪問的儲存區域,一般該區域位於通用RAM裡,

這個RAM叫隨機儲存器,是與CPU直接交換資料的記憶體儲存器,也叫主存,可以隨時隨地的寫,而且速度快,通常作為作業系統或其他正在執行中的程式的臨時資料儲存媒介。

在虛擬機器棧中,使用棧指標來訪問處理器。我們都學過棧這種資料結構,它是一種快速有效的 分配 儲存的方法,儲存速度僅次於暫存器,堆疊指標若向下移動,則分配新的記憶體,若向上移動則釋放那些記憶體。由於Java編譯器需要預先去生成相應的記憶體空間,所以,當我們嘗試建立程式的時候,Java編譯器必須知道被儲存在站內的所有資料的確切大小和宣告週期。一遍可以像上面描述的那樣去分配記憶體空間。

棧相對於堆的優勢就是比堆存取快,在棧中重要被用來存放一下基本型別的變數,例如int、short、long、byte、float、double、boolean、char,以及物件的引用(物件本身一般都存放在堆中)

StackOverFlow和OutOfMemoryError

Java虛擬機器規範允許Java棧的大小是動態的或者是固定不變的。如果執行緒在計算過程中,請求的棧深度大於最大可用的棧深度,則在程式執行過程中會丟擲StackOverFlow異常、如果Java棧可以動態擴充套件,而在擴充套件的過程中沒有足夠的記憶體空間支援棧的發展,在執行過程中會丟擲OutOfMemoryError異常。

本地方法棧

本地方法棧與虛擬機器棧所發揮的作用十分相似,區別就是虛擬機器棧執行Java(位元組碼)的方法,本地棧是為虛擬機器使用到Native方法。

Java堆

Java堆(Heap)是Java虛擬機器所管理的記憶體中最大的一塊。堆是被所有執行緒共享的一塊記憶體區域,在虛擬機器啟動時建立。次記憶體卻與的唯一目的就是存放物件示例,剛才在棧的部分也說了,棧中存的是物件的索引,而物件的例項存放在堆中。

在Java虛擬機器規範中描述:所有的物件例項以及陣列都要被在堆上分配記憶體。

GC(Garbage Collection)垃圾回收

由於堆和棧結構上的不同,所以其記憶體回收的機制也是不一樣的。

Java中對可以細分為:

  • 新生代
  • 老年代

再細分...

  • Eden空間
  • From Survivor空間
  • To Survivor

在記憶體的角度來看,執行緒共享的Java堆中可能劃分出多個執行緒私有的分配快取區(Thread Local Allocation Buffer,TLAB)。Java堆可以處於物理上不連續的記憶體空間中,只要邏輯上是連續的即可,就像我們的磁碟空間一樣,在實現是,既可以實現成固定大小的,也可以是可擴充套件的,不過當前主流的虛擬機器都是按照可擴充套件來實現的

-Xmx

-Xms
在堆中沒有記憶體完成例項分配,並且堆也無法在擴充套件時會丟擲OutOfMemoryError異常。

方法區

方法區和Java堆是一樣的,是各個執行緒共享的記憶體區域,他用於儲存已被虛擬機器載入的類的資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。

相關推薦

java記憶體分配

直接入正題,看看一下幾個例子,注意比較分析和理解:String a = “a1″;   String b = “a” + 1;   System.out.println((a == b)); //result = true  String a = “atrue”;   String b = “a” + “tr

Java記憶體分配策略

Java 記憶體分配策略 Java 程式執行時的記憶體分配策略有三種,分別是靜態分配,棧式分配,和堆式分配,對應的,三種儲存策略使用的記憶體空間主要分別是靜態儲存區(也稱方法區)、棧區和堆區。 靜態儲存區(方法區):主要存放靜態資料、全域性 static 資料和常量。這

JVM記憶體分配

JVM 記憶體分配   由於Java程式是交由JVM執行的,所以我們在談Java記憶體區域劃分的時候事實上是指JVM記憶體區域劃分。如下是具體java程式的執行過程:  首先Java原始碼檔案(.java字尾)會被Java編譯器編譯為位元組碼檔案(.class字尾),然後由JVM中的類

Java記憶體區域

一、執行時資料區域 Java在執行時,會根據需要,將記憶體區按照如下區域劃分,分為多個部分: 其中,藍色為執行緒共享的記憶體區域,橙色為執行緒獨享的記憶體區域。 1.1、方法區 儲存了虛擬機器載入的類資訊、常量、靜態變數等資料 1.2、常量區 是方法區的一部分,常用於存放編譯期生成的

C記憶體分配2

記憶體分配方式有三種: (1) 從靜態儲存區域分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的 整個執行期間都存在。例如全域性變數,static 變數。 (2) 在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函 數執行結束時這些儲

C記憶體分配1

關於C語言記憶體方面的話題要真說起來的話那恐怕就沒頭了,所以本文僅僅是一個淺談。 關於記憶體問題不同平臺之間有一定的區別。本文所指的平臺是x86的Linux平臺 用C語言做程式(其實其他語言也一樣),不僅要熟悉語法,其實很多相關的背景知識也很重要。在學習和研究C語言中記憶體

java記憶體分配問題

記憶體記憶體大家都知道(當然不是硬碟啊)。與c、c++相比呢,Java在記憶體管理的方面一個優越之處就是我們不用顯式的去對物件進行記憶體的分配和記憶體的回收,可能有人會著迷於對記憶體使用分配的這種快感,但是隨著程式變大,對於記憶體的維護工作也就越來越大。Java的JVM的自動

java堆疊和記憶體分配原理

在java中我們把java記憶體分為兩種一種是棧記憶體,一種則是堆記憶體 1.在談java堆疊知識之前我們先來看看java虛擬機器的自動垃圾回收機制 引用變數是普通的變數,定義時在棧中分配,引用變數在程式執行到其作用域之外後被釋放。而陣列和物件本身在堆中

java內存分配和回收策略

內存空間 高效率 cde map details 閾值 老年代 total 關於 一、導論   java技術體系中所提到的內存自動化管理歸根結底就是內存的分配與回收兩個問題,之前已經和大家談過java回收的相關知識,今天來和大家聊聊java對象的在內存中的分配。通俗的講,對

JVM篇:java虛擬機器記憶體模型

  博主最近嘗試著瞭解JVM,博主目前的一些理解,總之會隨著博主的深入瞭解慢慢完善吧 圖片來自網路 當JVM執行時,便會建立這五個區域,退出時銷燬。 JVM的五個區域:方法區、堆、棧(也可以稱為虛擬機器棧)、程式計數器、本地方法棧 博主在這裡說明一下:方法區概括了元空間

Java記憶體模型以及互動

本文的記憶體模型只寫虛擬機器記憶體模型,物理機的不予描述。   Java記憶體模型   在Java中,虛擬機器將執行時區域分成6中,如下圖:                   程式計數

JAVA驗證碼~

puts oid blog 方式 log 需求 .html index.jsp script 這兩天在幫同學做個項目,項目中需要做個驗證碼,說實話那麽多年竟然沒註意過這東西,原理很簡單,貼出來給大家做個參考。 1、簡單介紹 一般稍微有些經驗的程序員都不會再自己寫原生驗證碼生

Java中的hashCode方法

implement state ask get() 存在 rsa key 沖突 如何 哈希表這個數據結構想必大多數人都不陌生,而且在很多地方都會利用到hash表來提高查找效率。在Java的Object類中有一個方法: public native int hashCode(

Java集合框架

順序 eem map pre 叠代器 static 支持 print ted 集合框架最大的作用就是維護一組類型同樣的對象。僅僅是不同的類有不同的行為和性能。通常關註下面這些行為: 是否能存放反復的元素遍歷的順序是如何的是否支持多線程 以下首先介紹集合的經常使用,隨

Java的學習

override web ring 只知道 網頁標簽 insert語句 知識 reg 模型 Java就是用來做項目的!Java的主要應用領域就是企業級的項目開發!要想從事企業級的項目開發,你必須掌握如下要點: 1、掌握項目開發的基本步驟2、具備極強的面向對象的分析與設計技巧

java中內置的觀察者模式與動態代理的實現

所有 代理 notify play ani effect 一個 indicate protected 一.關於觀察者模式 1.將觀察者與被觀察者分離開來,當被觀察者發生變化時,將通知所有觀察者,觀察者會根據這些變化做出對應的處理。 2.jdk裏已經提供對應的Observer

Java中的深拷貝和拷貝

detail tle pac err @override 復制對象 deep har 間接   淺談Java中的深拷貝和淺拷貝(轉載) 原文鏈接: http://blog.csdn.net/tounaobun/article/details/8491392 假如說你想復制一

201671010116. 2016-2017-3《Java程序設計》Java

虛擬 專業 ble ise 解釋執行 long [] 程序編譯 orm 1.Java的工作方式:java把程序編譯為字節碼,字節碼可以在提供了Java虛擬機的任何系統上被解釋執行 。 源文件:文件名.java→字節碼文件:文件名.class→java虛擬機支持程序運行 2.

java異常[Exception]

你在 這也 一點 io操作 www. 新手 公司 manager other 淺談java異常[Exception] 一. 異常的定義 在《java編程思想》中這樣定義 異常:阻止當前方法或作用域繼續執行的問題。雖然java中有異常處理機制,但是要明確一點,決不應該

JAVA中“增強”類的某個方法的幾個中方法!

exc 目標 byte 相同 nbsp 優點 method value oca 一、繼承 使用場景:能夠控制這個類的構造的時候,才可以使用繼承。  優點:簡單容易使用, 缺點:耦合性大大的增強,不利於後期的維護,所以對於繼承這種方法,謹慎使用。 代碼實現:二、裝飾者模式