當前位置:首頁 » 存儲配置 » jvm欄位存儲

jvm欄位存儲

發布時間: 2023-04-06 02:38:12

『壹』 在java JVM里,如果一個變數被聲明為final或者static, 那麼這個變數的引用以及它的值被存放在哪

static不能用在孝激弊方法裡面,只能修飾類的屬性或者方法。
static修飾的變數被放在方法區,因為它屬於類變數,鉛派是類的一部分。
所有的方法中的普通變數都是在棧中的局部變數表中的,如果是引用類型的變數局部變數表會存放引用對象的地址,這巧族個引用對象實際存儲在堆中。如果被final修飾的話代表這個引用類型的變數指向的地址無法被改變。所以final修飾的引用的地址和final修飾的基本數據類型都會放在常量池,常量池位於方法區中。

『貳』 JVM方法區內存中 存儲的是 .class位元組碼文件么

不是位元組碼文件,內存中存儲的是,在類被引用(調用)時,JVM通如頃過李橡侍ClassLoader動態載入class文件形成的對象哪吵。

『叄』 重新理解jvm運行時的內存分布(堆棧方法區交互)

棧堆方法區的交互關系

java棧存儲的本地變數表,包括八種數據類型和引用類型,引用類型指向對象的地址,保存在reference,指向java堆,對象類型數據會保存變數名,變數類型,變數值等,這些會存在方法區中去查看(在初始化的時候)。

在java棧中會存放對象實例(s1),但是他對象旁汪實例中具體的數據會由java棧中的引用指向java堆中的地址,裡面的對象實例數據存放(實例名,實例相關類型,元數據信息。。。。),而靜態變數,常量,類載入後的信息等會存放在方法區,在運行時需要調用的時候去方法區取,所以方法區和java堆都是共享的。而java棧時線程獨有的數據(包括程序計數器,本地方法棧)。

一個jvm實例,只存在一個堆內存,堆內存的大小是可以調節的。類載入器讀取了類文件之後,需要把類,方法,常量放到堆內存中,保存所有的引用類型的真實信息,以方便執行器執行。堆內存分為三部分。

(養老區就是老年代)

堆內存 邏輯上 分為三部:新生 +養老 +方法區

eden+survivor+Spaces(元空間或者叫方法區或者Perm)

Perm 永久存儲區,是一個常駐內存的區域,用於存放jdk自身攜帶的Class,Interface的元數據,被裝載進此區域的數據是不會被垃圾回收器回收的,只有關閉jvm後才會釋放此區域所佔用的內存。

如果出現OutOfMemoryReeor: PermGen space 說明java虛擬機堆永久帶Perm內存設置不夠,答襪一半出現這種情況,都是程序啟動載入大量第三方jar呆滯的,

對於HotSpot虛擬機很多開發者習慣將方法區稱之為永久代(Parmenent
Gen),永久代是方法區的一個實現,這是不對的,方法區是邏輯上的部分。在jdk7中已經將原本放在永久代的字元串常量池移走了。

常量池( Constant Pool Constant PoolConstant Pool Constant Pool Constant Pool )是方法區的一部分, Class Class文件除了有類的版本、 欄位方法、介面等描述信息外,還有一項就是常量池這部分內容將在類載入後進入。

伊甸園區,所有對象剛new出來都會放在這里。

對象分兩種:
1.如果是大對象直接分配在Old區。
2.如果禁言了逃逸分析,會運舉仔在棧上分配。
以上兩種都不符合,放入伊甸園區。(Eden區)

看java7中如圖:

對比java8

『肆』 Java:字元串在JVM常量池中是如何存儲的呢

首先你要知道jvm常量池也是對象池,它和在堆中的存儲沒有區別(底層存儲都是一樣的,只是對象之間的引用有差別)。那為什麼要有常量池呢?因為它可以節省時間和空間,當需要一個對象的時候,可以直接從常量池中獲取,而不需要重新創建,擾余這樣也就節省了時間和空間(常量池判斷對象是否存在應該是equals方法)。
除了String外,Java的8種基本類型(Byte, Short, Integer, Long, Character, Boolean, Float, Double)除Float和Double以外,其它六種都實現了常量池。
樓主這么好學,我出個題目給樓主:
Integer i = 127;
Integer j = 127;
System.out.println(i == j);
提示:對象存在常量池

Integer m = 128;
Integer n = 128;
System.out.println(m == n);
提示謹李毀:對象存祥備在堆內存

『伍』 深入探索Java工作原理:JVM,內存回收及其他

Java語言引入了Java虛擬機 具有跨平台運行的功能 能夠很好地適應各種Web應用 同時 為了提高Java語言的性能和健壯性 還引入了如垃圾回收機制等新功能 通過這些改進讓Java具有其獨特的工作原理

.Java虛擬機

Java虛擬機(Java Virtual Machine JVM)是軟體模擬的計算機 它可以在任何處理器上(無論是在計算機中還是在其他電子設備中)安全兼容地執行保存在 class文件中的位元組碼 Java虛擬機的 機器碼 保存在 class文件中 有時也可以稱之為位元組碼文件

升大團Java程序的跨平台特性主要是指位元組碼文件可以在任何具有Java虛擬機的計算機或者電子設備上運行 Java虛擬機中的Java解釋器負責將位元組碼文件解釋成為特定的機器碼進行運行 因此在運行時 Java源程序需要通過編譯器編譯成為 class文件

Java虛擬機的建立需要針對不同的軟硬體平台來實現 既要考慮處理器的型號 也要考慮操作系統的種類 由此在SPARC結構 X 結構 MIPS和PPC等嵌入式處理晶元上 在UNIX Linux Windows和部分實時操作系統上都可實現Java虛擬機

.無用內存自動回收機制

在程序的執行過程中 部分內存在使用過後就處於廢棄狀態 如果不及時進行回收 很有可能會導致內存泄漏 進而引發系統崩潰 在C++語言中是由程序員進行內存回收的 程序員需要在編寫程序時把不再使用的對象內存釋放掉 這種人為管理內存釋放的方法往往由於程序員的疏忽而致使內存無法回收 同時也增加了程序員的工作量 而在Java運行環境中 始終存在著一個系統級的線程 專門跟蹤內存的使用情況 定期檢測出不再使用的內存 並自動進行回收 避免了內存的泄露 也減輕了程序員的工作量

.代碼安全性檢查機制

安全和方便總是相對矛盾的 Java編程語吵橘言的出現使得客戶端計算機可以方便地從網路上上傳或下載Java程序到本地計算機上運行 但是如何保證該Java程序不攜帶病毒或者沒有其他危險目的呢?為了確保Java程序執行的安全性 Java語言通過Applet程序來控制非法程序的安全性 也就是有了它才確保Java語言的生存

Java位元組碼的執行需要經過以下 個步驟

( )由類裝載器(class loader)負責把類文件( class文件)載入到Java虛擬機中 在此仿悉過程需要檢驗該類文件是否符合類文件規范

( )位元組碼校驗器(bytecode verifier)檢查該類文件的代碼中是否存在著某些非法操作 例如Applet程序中寫本地計算機文件系統的操作

( )如果位元組碼校驗器檢驗通過 由Java解釋器負責把該類文件解釋成為機器碼進行執行

注意

Java虛擬機採用 沙箱 運行模式 即把Java程序的代碼和數據都限制在一定內存空間里執行 不允許程序訪問該內存空間以外的內存 如果是Applet程序 還不允許訪問客戶端機器的文件系統

Java的運行環境

無論哪種語言都需要有它特定的運行環境 也就是平台 Java語言同樣不例外 但是如何理解Java程序與硬體環境無關呢?

幾乎所有的語言都需要通過編譯或者解釋才可以被計算機執行 但是Java有一點不同 它同時需要這兩個過程 其實 也正是因為這個原因才使Java這種語言具有了平台無關性 當完成一個Java源程序後 首先 通過Java翻譯程序將它編譯成一種叫做位元組碼的中間代碼 然後再由Java平台的解釋器將它轉換成為機器語言來執行 這一平台的核心就是JVM

Java的編譯過程與其他的語言不同 像C++這樣的語言 在編譯時它是與計算機的硬體平台信息密不可分的 編譯程序通過查表將所有指令的操作數和操作碼等轉換成內存的偏移量 即程序運行時的內存分配方式 目的是保證程序正常運行 而Java卻是將指令轉換成為一種 class的文件 這種文件不包含硬體的信息 需要執行時只要經過安裝有JVM的機器進行解釋 創建內存分配後再通過查表來確定一條指令所在的地址 這樣就有效地保證了Java的可移植性和安全性

Java平台具有這樣的特性和它的結構有關 通常一個程序運行的平台是一個硬體或者軟體運行的環境 目前比較流行的是Windows XP Linux Solaris和MacOS Java的平台不太一樣 它由兩個部分組成 即JVM和應用程序設計介面

.JVM

JVM是Java平台的核心 為了讓編譯產生的位元組碼能更好地解釋與執行 因此把JVM分成了 個部分 JVM解釋器 指令系統 寄存器 棧 存儲區和碎片回收區

◆JVM解釋器 即這個虛擬機處理欄位碼的CPU

◆JVM指令系統 該系統與計算機很相似 一條指令由操作碼和操作數兩部分組成 操作碼為 位二進制數 主要是為了說明一條指令的功能 操作數可以根據需要而定 JVM有多達 種不同的操作指令

◆寄存器 JVM有自己的虛擬寄存器 這樣就可以快速地與JVM的解釋器進行數據交換 為了功能的需要 JVM設置了 個常用的 位寄存器 pc(程序計數器) optop(操作數棧頂指針) frame(當前執行環境指針)和vars(指向當前執行環境中第一個局部變數的指針)

◆JVM棧 指令執行時數據和信息存儲的場所和控制中心 它提供給JVM解釋器運算所需要的信息

◆存儲區 JVM存儲區用於存儲編譯過後的位元組碼等信息

◆碎片回收區 JVM碎片回收是指將使用過的Java類的具體實例從內存進行回收 這就使得開發人員免去了自己編程式控制制內存的麻煩和危險 隨著JVM的不斷升級 其碎片回收的技術和演算法也更加合理 JVM 版後產生了一種叫分代收集技術 簡單來說就是利用對象在程序中生存的時間劃分成代 以此為標准進行碎片回收

.Java應用程序設計介面

Java Application Programming Interface簡稱Java API 其中文名為Java應用程序設計介面 它是一個軟體集合 其中有許多開發時所需要的控制項 可以用它來輔助開發

lishixin/Article/program/Java/hx/201311/26733

『陸』 jvm如何gc,新生代,老年代,持久代,都存儲哪些東西

虛擬機中共劃分為三個代:年輕代(即新生代)、年老代和持久代。
持久代主要存放的是Java類的類信息,與垃圾收集要收集的Java對象關系不大。
年輕代和年老代的劃分是對垃圾收集影響比較大的。
所有新生吵行虧成的對象首先都是放在年輕代的
年老代中存放的都是一些生命周期較長的對象。
持久代:用於存放靜態文件,升神如今Java類、方法等帶森。持久代對垃圾回收沒有顯著影響。

『柒』 java線程存放在jvm的哪個區域方法又存放在哪個區呢

聊到JAVA中的方法,大多數人對於方法存儲在方法區還是棧區(虛擬機棧)是很迷茫的。其實方法是存在方法區的下面我們就細細說一下JVM中的 方法區 VS 棧區方法區:用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據,方法編譯出的位元組碼也是保存在這

『捌』 Java構造函數(方法)存儲在jvm哪個內存里

存放到方法區當中;
new出來的是實例對象,實例對象才是存放在堆當中;
構造函數對應的是<init>方法,方法信息隨著類載入器載入到方法區當中。
棧:
以棧幀為單位,存放的不是方法具體的結構,只是通常一個方法對應一個棧幀,對應的入棧出棧就是棧幀的入棧出棧。棧幀中有局部變數表,操作數棧,方法返回地址,動態鏈接。其中局部變數表存放局部變數,喚沖包括形參,非靜態方法默認在第一個索引存放一個this變數;操作數棧用於操作局部變數表和一些值的運算,比如讀取表中變數的值進行運算,或存放相應的值到局部變數表中;方法返回地址則是用於記錄對應方法的下一條指令的地址;動態鏈接是符號引用變成的直接引用。
堆:
存放實例對象,在jdk7開始,還存放靜態變數和字元串常量池
方法區:
存放類元信息,比如完整類名全稱,public,abstract等修飾符,實現的介面消鏈基有序列表等;方法信息,比如修飾符,返回類型等;JIT代碼緩存,也就是被即時編譯器編譯後的熱點代碼,用於提高性能;域信息,也就是屬性信息,比拿謹如修飾符,類型等;運行時常量池,位元組碼文件中常量池的運行時表現,類似符號引用的記錄,不過蘊含的信息更為豐富,而且具有動態性。jdk6及以前,還存放靜態變數,運行時常量池中還存放字元串常量池,到了jdk7則移到了堆中。

『玖』 ElasticSearch存儲

使用ElasticSearch快一年了,自認為相關API使用的還比較6,產品提的一些搜索需求實現起來都從心應手;但是前幾天同事的一個問題直接將我打回到小白,同事問了句:「 ElasticSearch的索引是怎麼存儲的?刪除文檔和更新文檔是怎麼實現的? 」,當時我就懵逼了,說了句得查一下,好尷尬......
回想起來發現自己從來都沒有深入了解過這些細節,於是便覺得非常有必要對ElasticSearch的文檔存儲做一次深入的了解,知其然不知其所以然對於我們來說是遠遠不夠的,在ElasticSearch中,文檔( Document )存儲的介質分為內存和硬碟兩種:

同時,ElasticSearch進程自身的運行也需要內存空間,必須保證ElasticSearch進程有充足的運行時內存。為了使ElasticSearch引擎達到最佳性能,必須合理分配有限的內存和硬碟資源。

ElasticSearch引擎把文檔數據寫入到倒排索引( Inverted Index )的數據結構中,倒排索引建立備桐的是分詞( Term )和文檔( Document )之間的映射關系,在倒排索引中,數據是面向詞( Term )而不是面向姿帆文檔( Document )的。
舉個栗子,假設我們有兩個文檔,每個文檔的content域包含如下內容:
1. The quick brown fox jumped over the lazy dog
2. Quick brown foxes leap over lazy dogs in summer
文檔和詞之間的關系如下圖:

欄位值被分析之後,存儲在倒排索引中,倒排索引存儲的是分詞( Term )和文檔( Doc )之間的關系,簡化版的倒排索引如下圖:

從圖中可以看出,倒排索引有一個詞條的列表,每個分詞在列表中是唯一的,記錄著詞條出現的次數,以及包含詞條的文檔。實際中ElasticSearch引擎創建的倒排索引比這個復雜得多。

段是倒排索引的組成部分,倒排索引是由段( Segment )組成的,段存儲在硬碟( Disk )文件中。 索引段不是實時更新的,這意味著,段在寫入硬碟之後,就不再被更新。在刪除文檔時,ElasticSearch引擎把已刪除的文檔的信息存儲在一個單獨的文件中,在搜索數據時,ElasticSearch引擎首先從段中執行查詢,再從查詢結果中過濾被刪除的文檔 。這意味著,段中存儲著被刪除的文檔,這使得段中含有」正常文檔「的密度降低。

多個段可以通過段合並(Segment Merge)操作把「已刪除」的文檔將從段中物理刪除,把未刪除的文檔合並到一個新段中,新段中沒有」已刪除文檔「,因此,段合並操作能夠提高索引的查找速度 ;但是,段合並是IO密集型操作,需要消耗大量的硬碟IO。

在ElasticSearch中,大多數查詢都需要從硬碟文件(索引的段數據存儲在硬碟文件中)中獲取數據;因此, 在全局配置文件elasticsearch.yml 中,把結點的路徑(Path)配置為性能較高的硬碟,能夠提高查詢性能 。默認情況下,ElasticSearch使用基於安裝目錄的相對路徑來配置結點的路徑,安裝目錄由屬性path.home顯示,在home path下,ElasticSearch自動創建config,data,logs和plugins目錄,一般情況下不需要對結點路徑單獨配置。結點的文件路徑配置項:
path.data:設置ElasticSearch結點的索引數據保存的目錄,多個數據文件使用逗號隔開。
例如,path.data: /path/to/data1,/path/to/data2

path.work:設置ElasticSearch的臨時文件保存的目錄;

映射參數index決定ElasticSearch引擎是否對文本字仿冊坦段執行分析操作,也就是說分析操作把文本分割成一個一個的分詞,也就是標記流( Token Stream ),把分詞編入索引,使分詞能夠被搜索到:
1) 當index為analyzed時,該欄位是分析欄位,ElasticSearch引擎對該欄位執行分析操作,把文本分割成分詞流,存儲在倒排索引中,使其支持全文搜索。
2)當index為not_analyzed時,該欄位不會被分析,ElasticSearch引擎把原始文本作為單個分詞存儲在倒排索引中,不支持全文搜索,但是支持詞條級別的搜索;也就是說,欄位的原始文本不經過分析而存儲在倒排索引中,把原始文本編入索引,在搜索的過程中,查詢條件必須全部匹配整個原始文本。
3)當index為no時,該欄位不會被存儲到倒排索引中,不會被搜索到。

欄位的原始值是否被存儲到倒排索引,是由映射參數store決定的,默認值是false,也就是,原始值不存儲到倒排索引中。
映射參數index和store的區別在於:
store用於獲取(Retrieve)欄位的原始值,不支持查詢,可以使用投影參數fields,對stroe屬性為true的欄位進行過濾,只獲取(Retrieve)特定的欄位,減少網路負載;
index用於查詢(Search)欄位,當index為analyzed時,對欄位的分詞執行全文查詢;當index為not_analyzed時,欄位的原始值作為一個分詞,只能對欄位的原始文本執行詞條查詢;

如果設置欄位的index屬性為not_analyzed,原始文本將作為單個分詞,其最大長度跟UTF8 編碼有關,默認的最大長度是32766Bytes(約32KB),如果欄位的文本超過該限制,那麼ElasticSearch將跳過( Skip )該文檔,並在Response中拋出異常消息:
operation[607]: index returned 400 _index: ebrite _type: events _id: 76860 _version: 0 error: Type: illegal_argument_exception Reason: "Document contains at least one immense term in field="event_raw" (whose UTF8 encoding is longer than the max length 32766), all of which were skipped. Please correct the analyzer to not proce such terms. The prefix of the first immense term is: '[112, 114,... 115]...', original message: bytes can be at most 32766 in length; got 35100" CausedBy:Type: max_bytes_length_exceeded_exception Reason: "bytes can be at most 32766 in length; got 35100"

可以在欄位中設置ignore_above屬性,該屬性值指的是字元數量,而不是位元組數量;由於一個UTF8字元最多佔用3個位元組,因此,可以設置
「ignore_above」:10000
這樣,超過30000位元組之後的字元將會被分析器忽略,單個分詞( Term )的最大長度是30000Bytes。
The value for ignore_above is the character count, but Lucene counts bytes. If you use UTF-8 text with many non-ASCII characters, you may want to set the limit to 32766 / 3 = 10922 since UTF-8 characters may occupy at most 3 bytes.

默認情況下,大多數欄位被索引之後,能夠被搜索到。 倒排索引是由一個有序的詞條列表構成的,每一個詞條在列表中都是唯一存在的,通過這種數據存儲模式,你可以很快查找到包含某一個詞條的文檔列表

但是,排序和聚合操作採用相反的數據訪問模式,這兩種操作不是查找詞條以發現文檔,而是查找文檔,以發現欄位中包含的詞條。ElasticSearch使用列式存儲實現排序和聚合查詢。
文檔值( doc_values )是存儲在硬碟上的數據結構,在索引時( index time )根據文檔的原始值創建,文檔值是一個列式存儲風格的數據結構,非常適合執行存儲和聚合操作,除了字元類型的分析欄位之外,其他欄位類型都支持文檔值存儲。默認情況下,欄位的文檔值存儲是啟用的,除了字元類型的分析欄位之外。如果不需要對欄位執行排序或聚合操作,可以禁用欄位的文檔值,以節省硬碟空間。

字元類型的分析欄位,不支持文檔值(doc_values),但支持fielddata數據結構。fielddata數據結構存儲在JVM的堆內存中。相比文檔值(數據存儲在硬碟上),fielddata欄位(數據存儲在內存中)的查詢性能更高。默認情況下,ElasticSearch引擎在第一次對欄位執行聚合或排序查詢時(query-time),創建fielddata數據結構;在後續的查詢請求中,ElasticSearch引擎使用fielddata數據結構以提高聚合和排序的查詢性能。

在ElasticSearch中,倒排索引的各個段( segment )的數據存儲在硬碟文件上,從整個倒排索引的段中讀取欄位數據之後,ElasticSearch引擎首先反轉詞條和文檔之間的關系,創建文檔和詞條之間的關系,即創建順排索引,然後把順排索引存儲在JVM的堆內存中。把倒排索引載入到fielddata結構是一個非常消耗硬碟IO資源的過程。因此,數據一旦被載入到內存,最好保持在內存中,直到索引段( segment )的生命周期結束。

默認情況下,倒排索引的每個段( segment ),都會創建相應的fielddata結構,以存儲字元類型的分析欄位值,但是,需要注意的是,分配的JVM堆內存是有限的,Fileddata把數據存儲在內存中,會佔用過多的JVM堆內存,甚至耗盡JVM賴以正常運行的內存空間,反而會降低ElasticSearch引擎的查詢性能。

fielddata會消耗大量的JVM內存,因此,盡量為JVM設置大的內存,不要為不必要的欄位啟用fielddata存儲。通過format參數控制是否啟用欄位的fielddata特性,字元類型的分析欄位,fielddata的默認值是paged_bytes,這就意味著,默認情況下,字元類型的分析欄位啟用fielddata存儲。一旦禁用fielddata存儲,那麼字元類型的分析欄位將不再支持排序和聚合查詢。

loading屬性控制fielddata載入到內存的時機,可能的值是lazy,eager和eager_global_ordinals,默認值是lazy。
lazy:fielddata只在需要時載入到內存,默認情況下,在第一次搜索時,fielddata被載入到內存中;但是,如果查詢一個非常大的索引段(Segment),lazy載入方式會產生較大的時間延遲。
eager:在倒排索引的段可用之前,其數據就被載入到內存,eager載入方式能夠減少查詢的時間延遲,但是,有些數據可能非常冷,以至於沒有請求來查詢這些數據,但是冷數據依然被載入到內存中,佔用緊缺的內存資源。
eager_global_ordinals:按照global ordinals積極把fielddata載入到內存。

ElasticSearch使用 JAVA_OPTS 環境變數( Environment Variable )啟動JVM進程,在 JAVA_OPTS 中,最重要的配置是: -Xmx參數控制分配給JVM進程的最大內存,-Xms參數控制分配給JVM進程的最小內存 。(在ElasticSearch啟動命令後面可以通過參數方式配置,如: /usr/local/elasticsearch/bin/elasticsearch -d --Xmx=10g --Xms=10g )通常情況下,使用默認的配置就能滿足工程需要。
ES_HEAP_SIZE 環境變數控制分配給JVM進程的堆內存( Heap Memory )大小,順排索引( fielddata )的數據存儲在堆內存( Heap Memory )中。

大多數應用程序嘗試使用盡可能多的內存,並盡可能把未使用的內存換出,但是,內存換出會影響ElasticSearch引擎的查詢性能,推薦啟用內存鎖定,禁用ElasticSearch內存的換進換出。
在全局配置文檔 elasticsearch.yml 中,設置 bootstrap.memory_lock 為ture,這將鎖定ElasticSearch進程的內存地址空間,阻止ElasticSearch內存被OS換出( Swap out )。

通過學習,算是對ElasticSearch索引存儲及更新有了一個較深的了解,至少能讓我從容去面對同事的提問,但與此同時給我敲響了警鍾,在使用一門技術的同時,更應該去了解它具體的原理,而不僅僅是停留在使用級別;在學習的路上,我們仍需要更加努力......

『拾』 JVM原理是什麼

首先這里澄清兩個概念:JVM實例和JVM執行引擎實例,JVM實例對應了一個獨立運行的Java程序,而JVM執行引擎實例則對應了屬於用戶運行程序的線程;也就是JVM實例是進程級別,而執行引擎是線程級別的。JVM是什麼?—JVM的生命周期JVM實例的誕生:當啟動一個Java程序時,一個JVM實例就產生了,任何一個擁有publicstaticvoidmain(String[]args)函數的class都可以作為JVM實例運行的起點,既然如此,那麼JVM如何知道是運行classA的main而不是運行classB的main呢?這就需要顯式的告訴JVM類名,也就是我們平時運行Java程序命令的由來,如JavaclassAhelloworld,這里Java是告訴os運行SunJava2SDK的Java虛擬機,而classA則指出了運行JVM所需要的類名。JVM實例的運行:main()作為該程序初始線程的起點,任何其他線程均由該線程啟動。JVM內部有兩種線程:守護線程和非守護線程,main()屬於非守護線程,守護線程通常由JVM自己使用,Java程序也可以標明自己創建的線程是守護線程。JVM實例的消亡:當程序中的所有非守護線程都終止時,JVM才退出;若安全管理器允許,程序也可以使用Runtime類或者System.exit()來退出。JVM是什麼?—JVM的體系結構粗略分來,JVM的內部體系結構分為三部分,分雹山別是:類裝載器(ClassLoader)子系統,運行時數據區,和執行引擎。下面將先介紹類裝載器,然後是執行引擎,最後是運行時數據區1、類裝載器,顧名思義,就是用來裝載.class文件的。JVM的兩種類裝載器包括:啟動類裝載器和用戶自定義類裝載器,啟動類裝載器是JVM實現的一部分,用戶自定義類裝載器則是Java程序的一部分,必須是ClassLoader類的子類。(下面所述情況是針對SunJDK1.2)動類裝載器:只在系統類(JavaAPI的類文件)的安裝路徑查找要裝入的類用戶自定義類裝載器:系統類裝載器:在JVM啟動時創建,用來在CLASSPATH目錄下查找要裝入的類其他用戶自定義類裝載器:這里有必要先說一下ClassLoader類的幾個方法,了解它們對於了解自定義類裝載器如何裝載.class文件至關重要。(Stringname,bytedata[],intoffset,intlength) (Stringname,bytedata[],intoffset,intlength,);(Stringname) (Classc) defineClass用來將二進制class文件(新類型)導入到方法區,也就是這里指的類是用戶自定義的類(也就是負責裝載類)明乎findSystemClass通過類型的全限定名,先通過系統類裝載器或者啟動類裝載器來激肆悉裝載,並返回Class對象。ResolveClass:讓類裝載器進行連接動作(包括驗證,分配內存初始化,將類型中的符號引用解析為直接引用),這里涉及到Java命名空間的問題,JVM保證被一個類裝載器裝載的類所引用的所有類都被這個類裝載器裝載,同一個類裝載器裝載的類之間可以相互訪問,但是不同類裝載器裝載的類看不見對方,從而實現了有效的屏蔽。2、執行引擎:它或者在執行位元組碼,或者執行本地方法要說執行引擎,就不得不的指令集,每一條指令包含一個單位元組的操作碼,後面跟0個或者多個操作數。(一)指令集以棧為設計中心,而非以寄存器為中心這種指令集設計如何滿足Java體系的要求:平台無關性:以棧為中心使得在只有很少register的機器上實現Java更便利compiler一般採用stack向連接優化器傳遞編譯的中間結果,若指令集以stack為基礎,則有利於運行時進行的優化工作與執行即時編譯或者自適應優化的執行引擎結合,通俗的說就是使編譯和運行用的數據結構統一,更有利於優化的開展。網路移動性:class文件的緊湊性。安全性:指令集中絕大部分操作碼都指明了操作的類型。(在裝載的時候使用數據流分析期進行一次性驗證,而非在執行每條指令的時候進行驗證,有利於提高執行速度)。(二)執行技術主要的執行技術有:解釋,即時編譯,自適應優化、晶元級直接執行其中解釋屬於第一代JVM,即時編譯JIT屬於第二代JVM,自適應優化(目前Sun的HotspotJVM採用這種技術)則吸取第一代JVM和第二代JVM的經驗,採用兩者結合的方式自適應優化:開始對所有的代碼都採取解釋執行的方式,並監視代碼執行情況,然後對那些經常調用的方法啟動一個後台線程,將其編譯為本地代碼,並進行仔細優化。若方法不再頻繁使用,則取消編譯過的代碼,仍對其進行解釋執行。3、運行時數據區:主要包括:方法區,堆,Java棧,PC寄存器,本地方法棧(1)方法區和堆由所有線程共享堆:存放所有程序在運行時創建的對象方法區:當JVM的類裝載器載入.class文件,並進行解析,把解析的類型信息放入方法區。(2)Java棧和PC寄存器由線程獨享,在新線程創建時間里(3)本地方法棧:存儲本地方法調用的狀態上邊總體介紹了運行時數據區的主要內容,下邊進行詳細介紹,要介紹數據區,就不得不說明JVM中的數據類型。JVM中的數據類型:JVM中基本的數據單元是word,而word的長度由JVM具體的實現者來決定數據類型包括基本類型和引用類型,(1)基本類型包括:數值類型(包括除boolean外的所有的Java基本數據類型),boolean(在JVM中使用int來表示,0表示false,其他int值均表示true)和returnAddress(JVM的內部類型,用來實現finally子句)。(2)引用類型包括:數組類型,類類型,介面類型前邊講述了JVM中數據的表示,下面讓我們輸入到JVM的數據區首先來看方法區:上邊已經提到,方法區主要用來存儲JVM從class文件中提取的類型信息,那麼類型信息是如何存儲的呢?眾所周知,Java使用的是大端序(big?endian:即低位元組的數據存儲在高位內存上,如對於1234,12是高位數據,34為低位數據,則Java中的存儲格式應該為12存在內存的低地址,34存在內存的高地址,x86中的存儲格式與之相反)來存儲數據,這實際上是在class文件中數據的存儲格式,但是當數據倒入到方法區中時,JVM可以以任何方式來存儲它。類型信息:包括class的全限定名,class的直接父類,類類型還是介面類型,類的修飾符(public,等),所有直接父介面的列表,Class對象提供了訪問這些信息的窗口(可通過Class.forName(「」)或instance.getClass()獲得),下面是Class的方法,相信大家看了會恍然大悟,(原來如此J)getName(),getSuperClass(),isInterface(),getInterfaces(),getClassLoader();static變數作為類型信息的一部分保存指向ClassLoader類的引用:在動態連接時裝載該類中引用的其他類指向Class類的引用:必然的,上邊已述該類型的常量池:包括直接常量(String,integer和floatpoint常量)以及對其他類型、欄位和方法的符號引用(注意:這里的常量池並不是普通意義上的存儲常量的地方,這些符號引用可能是我們在編程中所接觸到的變數),由於這些符號引用,使得常量池成為Java程序動態連接中至關重要的部分欄位信息:普通意義上的類型中聲明的欄位方法信息:類型中各個方法的信息編譯期常量:指用final聲明或者用編譯時已知的值初始化的類變數class將所有的常量復制至其常量池或者其位元組碼流中。方法表:一個數組,包括所有它的實例可能調用的實例方法的直接引用(包括從父類中繼承來的)除此之外,若某個類不是抽象和本地的,還要保存方法的位元組碼,操作數棧和該方法的棧幀,異常表。舉例:classLava{ privateintspeed=5; voidflow(){} classVolcano{ publicstaticvoidmain(String[]args){ Lavalava=newLava(); lava.flow(); } } 運行命令JavaVolcano;(1)JVM找到Volcano.class倒入,並提取相應的類型信息到方法區。通過執行方法區中的位元組碼,JVM執行main()方法,(執行時會一直保存指向Vocano類的常量池的指針)(2)Main()中第一條指令告訴JVM需為列在常量池第一項的類分配內存(此處再次說明了常量池並非只存儲常量信息),然後JVM找到常量池的第一項,發現是對Lava類的符號引用,則檢查方法區,看Lava類是否裝載,結果是還未裝載,則查找「Lava.class」,將類型信息寫入方法區,並將方法區Lava類信息的指針來替換Volcano原常量池中的符號引用,即用直接引用來替換符號引用。(3)JVM看到new關鍵字,准備為Lava分配內存,根據Volcano的常量池的第一項找到Lava在方法區的位置,並分析需要多少對空間,確定後,在堆上分配空間,並將speed變數初始為0,並將lava對象的引用壓到棧中(4)調用lava的flow()方法好了,大致了解了方法區的內容後,讓我們來看看堆Java對象的堆實現:Java對象主要由實例變數(包括自己所屬的類和其父類聲明的)以及指向方法區中類數據的指針,指向方法表的指針,對象鎖(非必需),等待集合(非必需),GC相關的數據(非必需)(主要視GC演算法而定,如對於標記並清除演算法,需要標記對象是否被引用,以及是否已調用finalize()方法)。那麼為什麼Java對象中要有指向類數據的指針呢?我們從幾個方面來考慮首先:當程序中將一個對象引用轉為另一個類型時,如何檢查轉換是否允許?需用到類數據其次:動態綁定時,並不是需要引用類型,而是需要運行時類型,這里的迷惑是:為什麼類數據中保存的是實際類型,而非引用類型?這個問題先留下來,我想在後續的讀書筆記中應該能明白指向方法表的指針:這里和C++的VTBL是類似的,有利於提高方法調用的效率對象鎖:用來實現多個線程對共享數據的互斥訪問等待集合:用來讓多個線程為完成共同目標而協調功過。(注意Object類中的wait(),notify(),notifyAll()方法)。Java數組的堆實現:數組也擁有一個和他們的類相關聯的Class實例,具有相同dimension和type的數組是同一個類的實例。數組類名的表示:如[[LJava/lang/Object表示Object[][],[I表示int[],[[[B表示byte[][][]至此,堆已大致介紹完畢,下面來介紹程序計數器和Java棧程序計數器:為每個線程獨有,在線程啟動時創建,若thread執行Java方法,則PC保存下一條執行指令的地址。若thread執行native方法,則Pc的值為undefinedJava棧:Java棧以幀為單位保存線程的運行狀態,Java棧只有兩種操作,幀的壓棧和出棧。每個幀代表一個方法,Java方法有兩種返回方式,return和拋出異常,兩種方式都會導致該方法對應的幀出棧和釋放內存。幀的組成:局部變數區(包括方法參數和局部變數,對於instance方法,還要首先保存this類型,其中方法參數按照聲明順序嚴格放置,局部變數可以任意放置),操作數棧,幀數據區(用來幫助支持常量池的解析,正常方法返回和異常處理)。本地方法棧:依賴於本地方法的實現,如某個JVM實現的本地方法借口使用C連接模型,則本地方法棧就是C棧,可以說某線程在調用本地方法時,就進入了一個不受JVM限制的領域,也就是JVM可以利用本地方法來動態擴展本身。相信大家都明白JVM是什麼了吧。原文鏈接: http://www.cnblogs.com/chenzhao/archive/2011/08/14/2137713.html

熱點內容
php房產網 發布:2025-02-13 18:18:06 瀏覽:85
源碼資源吧 發布:2025-02-13 18:14:39 瀏覽:79
java培訓價錢 發布:2025-02-13 17:59:33 瀏覽:974
c語言中變數類型 發布:2025-02-13 17:52:20 瀏覽:258
ftp導出報錯 發布:2025-02-13 17:41:20 瀏覽:997
腳本下載教程 發布:2025-02-13 17:39:06 瀏覽:235
解壓密碼re 發布:2025-02-13 17:39:02 瀏覽:558
linuxdump內存 發布:2025-02-13 17:37:30 瀏覽:57
游戲客戶端源碼 發布:2025-02-13 17:37:19 瀏覽:594
win7打開文件夾聲音 發布:2025-02-13 17:35:03 瀏覽:606