JVM——引言+JVM內存結構

引言

什么是JVM

定義:

Java VirtualMachine -java 程序的運行環境 (ava 二進制字節碼的運行環境)

好處:

  • 一次編寫,到處運行
  • 自動內存管理,垃圾回收功能
  • 數組下標越界檢查,
  • 多態

比較:

jvm jre jdk

學習jvm的作用

  • 面試
  • 理解底層實現原理
  • 中高級程序員的必備技能

常見的jvm

自己百度查找

jvm的組成

?內存結構

程序計數器

定義

Program Counter Register 程序計數器(寄存器)

作用

如下圖所示

右邊就是簡單的java代碼打印操作,編譯成左側的二進制字節碼。

經過解釋器——>機器碼——>CPU執行。

程序計數器在這里面的作用就是記住下一條jvm指令的執行地址。

第一條指令地址是0,第一條指令交給解釋器去執行的同時會把第二條指令的地址3放入程序計數器。第一條執行完之后,解釋器會去取出3來執行......

物理實現: 通過CPU中寄存器(速度快)實現

?特點:

線程私有

每個線程都有自己的程序計數器。

每一個線程會有被分配一個時間片,在當前時間片內不能執行完會去執行別的線程的代碼,直到輪到下一個時間片。

切換到別的線程時要記住當前執行到哪里,還是要用到程序計數器。通過私有的程序計數器知道下一行代碼的地址。

?唯一不會存在內存溢出的區

虛擬機棧

棧是一種普通的先進后出的數據結構。

java的虛擬機棧則是線程運行需要的內存空間

一段代碼有多個方法組成,一個棧幀表示一次方法的調用,棧幀就是每個方法運行需要的內存

運行:調用第一個方法時會給第一個方法劃分一個棧幀空間,并壓入棧內,執行完后會出棧,也會釋放該方法占用的內存。

然后方法1調用方法2時會產生一個方法2的棧幀并入棧,然后方法2調用方法3也會產生并入棧,如下圖所示。

?定義

Java Virtual Machine Stacks (Java 虛擬機棧)

  • 每個線程運行時所需要的內存,稱為虛擬機棧
  • 每個棧由多個棧幀 (Frame) 組成,對應著每次方法調用時所占用的內存
  • 每個線程只能有一個活動棧幀,對應著當前正在執行的那個方法?

棧幀大小由方法里的參數以及局部變量的個數決定?

問題辨析

1.垃圾回收是否涉及棧內存?

? ?棧內存是一次次方法調用產生的棧幀內存,調用結束后會彈出棧,會自動回收,不需要垃圾回收? ? ?管理,垃圾回收是回收堆內存中的無用對象。

2.棧內存分配越大越好嗎?

運行java代碼時是可以指定棧內存大小的,使用-Xss size,下圖還有不同系統下默認棧內存的大小和設定內存的示例。

棧內存越大會讓線程數變少,512mb的物理內存下,每個線程的棧內存設置1mb大小可以運行512個,設置2mb大小可以運行256個線程。不會提高線程效率,但可以增加遞歸的層數。

????????

3.方法內的局部變量是否線程安全?

? ? ? ? 根據該變量是每個線程共享還是線程私有判斷。下圖是一個方法,方法內有一個局部變量。

該方法被調用兩次時會有兩個不同的棧。每個線程都會有私有的局部變量。因此這里不會有線程干擾的問題。

?假如將x改為static int x=0;的話就會出現線程干擾,如果不加保護的話會有線程安全問題。

總結:共享需要考慮線程安全,私有就不需要考慮。

  • 如果方法內的局部變量沒有逃離方法的作用范圍,則是線程安全。
  • 如果是局部變量引用了對象,并逃離方法的作用方法,需要考慮線程安全(引用傳遞和值傳遞的問題)

棧內存溢出

  • 棧幀過多導致棧內存溢出(棧幀過多爆棧)? :? 通常在的遞歸導致。
  • 單片棧幀過大導致棧內存溢出(太大了,已經塞滿了)

?一般不會有單片過大,棧幀里都是方法參數和局部變量。可以通過設置棧內存大小達到

?在將對象轉換成json對象時也會有棧溢出,這種兩個類的循環問題會導致json解釋器出現問題。

?可以通過一個@JsonIgnore注解達到在json轉換對象時忽略變量的效果。?

?

線程運行診斷

案例1: cpu 占用過多

?linux環境下運行一段java代碼導致cpu占用過高,可以使用top命令定位到哪一個進程占用,但看不見是哪一個線程導致的。

在linux下使用ps H -eo pid,tid,%cpu 命令可以看見所有線程的pid(進程號),tid(線程號),%cpu(cpu占用)。

使用ps H -eo pid,tid,%cpu | grep 32655? ?后面加上| grep pid過濾無關進程的線程。

  • 用top定位哪個進程對cpu的占用過高
  • ps H -eo pid,tid,%cpu | grep pid (用ps命令進一步定位是哪個線程引起的cpu占用過高)
  • jstack 進程id? (可以根據線程id 找到有問題的線程,進一步定位到問題代碼的源碼行號)

生產環境不推薦jstack,因為打印線程信息jvm會暫停其他線程?

然后將線程編號32665轉換成16進制(7F99)在輸出內容中查找?

?在jstack 輸出內容中可以看見一個nid=Ox7f99的線程,狀態為RUNNABLE.

看見問題出在第8行代碼。如下圖源碼第8行是個死循環。

?nid、pid 和 tid 是計算機系統中常用的三個標識

  • nid (Node ID) 是指在分布式系統中,每個節點的唯一標識
  • pid (Process ID) 是指操作系統中每個進程的唯一標識。
  • tid (Thread ID) 是指操作系統中每個線程的唯一標識。

案例2: 程序運行很長時間沒有結果

線程死鎖導致的無結果下使用jstack命令查看,下輸出內容最后可以看見有關死鎖信息。

?兩個線程都想獲得a,b,但是都在等對方放開擁有的對象,然后陷入死鎖。

產生死鎖的四個必要條件:互斥、不可剝奪、請求和保持、循環等待。

本地方法棧

定義:? ? java虛擬機在調用本地方法時需要給本地方法提供的內存空間

在Object這個類中就有很多,比如Object的clone方法的聲明是native,這個native的實現是c/c++,java代碼是間接調用native

?

定義

通過 new 關鍵字,創建對象都會使用堆內存

特點:

  • 它是線程共享的,堆中對象都需要考慮線程安全的問題
  • 有垃圾回收機制 (不再被引用的對象會被回收)?

堆內存溢出

下圖所示方法中String類型的對象a會一次次變大,直至堆溢出。

?運行結果:? 溢出內存錯誤: java 堆 空間

使用-Xmx size改變堆空間大小。

?

?修改前26次才溢出,修改后17次溢出。

有可能堆內存較大,運行時間短,在系統前期看不出問題,后期才會爆掉,故測試時可以將堆內存設置較小進行排查。

堆內存診斷

相關工具:

1.jps 工具

????????查看當前系統中有哪些 java 進程

2. jmap 工具

????????查看堆內存占用情況 jmap -heap 進程id?(只能看某一瞬間的情況)

3.jconsole 工具?

????????圖形界面的,多功能的監測工具,可以連續監測

4.jvisualVM 工具

? ? ? ? 圖形化界面,可以抓取當前快照?

案例1

?new一個10MB的數組對象,后面置為null,然后gc顯式回收。

運行后通過jps查看進程id,jmap -heap 18756在1~2,2~3,3之后三個時間點抓取快照信息。?

最大堆內存占用MaxHeapSize是4個G?

?

Eden Space就是專門為new 出來的對象準備的。?

?1~2之間

數組創建之前使用了6Mb

?2~3之間

創建數組對象之后使用16mb,

?3之后

垃圾回收之后變成1.2mb

使用jconsole工具的界面。

?案例2

垃圾回收之后,內存占用任然很高。

新生代被回收了,老年代沒有被回收。

?新生代剩8mb

?老年代剩200mb

使用新的工具jvisualvm可視化虛擬機

?

保存快照之后進行查找最大的類?

?查看最大的ArrayList實例的具體信息

?源代碼

兩百個Student對象,每個都開了一個1mb大小的byte數組。并且一直在作用范圍內,無法回收,內存占用居高不下。

?通過可視化界面的堆 dump按鈕進行排查。?

方法區

定義

按照jdk_jvm_1.8中的定義

  • 方法區是所有java虛擬區線程共享的區域。
  • 存儲了和類的結構相關的信息。
  • 有成員變量filed,method data方法數據,成員方法、構造器方法的代碼以及運行時常量值run-time constant pool等等
  • 在虛擬機啟動時被創建
  • 邏輯上是堆的組成部分(1.8以前用的堆內存,1.8以后用的是系統內存
  • 方法區也會導致內存溢出

組成

永久代和元空間都是方法區這個概念的實現。

永久代和元空間最本質的區別就是 前者使用的是jvm內存 后者使用的是操作系統內存。

圖中常量池是運行時常量池。

?方法區內存溢出

  • 1.8 以前會導致永久代內存溢出
  • 1.8 之后會導致元空間內存溢出

下圖代碼就是一個加載了10000個類的代碼,最外層繼承實現了類加載器,在循環內指定版本號,類名,包名,父類,接口等信息創建一個新類。

這里元空間和永久代都沒有設置上限,這里需要設置元空間和永久代大小。

-XX:MaxMetaspaceSize=8m? 元空間

-XX:MaxPermSize=8m? 永久代

元空間運行報異常?

?永久代報異常

?場景:

  • spring
  • mybatis

spring和mybatis都使用到了cglib技術。

運行時常量池

下面的這段代碼的二進制字節碼含有如下信息。?

使用如下命令查看該代碼反編譯后的結果

javap -v HelloWorld.class

常量池部分

?虛擬機指令部分

執行指令時下面第一條就是獲取靜態變量,#2在常量池里面找。

ldc是找到一個引用地址。

?定義:

  • 常量池,就是一張表,虛擬機指令根據這張常量表找到要執行的類名、方法名、參數類型、字面量等信息
  • 運行時常量池,常量池是*.class 文件中的,當該類被加載,它的常量池信息就會放入運行時常量池,并把里面的符號地址變為真實地址

?運行時常量池里面#1,#2...這些會變成內存地址。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/42892.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/42892.shtml
英文地址,請注明出處:http://en.pswp.cn/news/42892.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

神經網絡基礎-神經網絡補充概念-63-殘差網絡

概念 殘差網絡(Residual Network,ResNet)是一種深度卷積神經網絡結構,旨在解決深層網絡訓練中的梯度消失和梯度爆炸問題,以及幫助訓練非常深的網絡。ResNet 在2015年被提出,其核心思想是引入了"殘差塊…

前端-ES6

let 和 const 為了解決var的作用域的問題,而且var 有變量提升,會出現全局污染的問題 let 塊狀作用域,并且不能重復聲明const 一般用于聲明常量,一旦被聲明無法修改,但是const 可以聲明一個對象,對象內部的…

工作時使用redis,kafka查閱的資料鏈接

不分先后 一 、redis查閱地址 一篇文章講清楚RedisRedis原理介紹一篇詳文帶你入門 Redis內存耗盡后Redis會發生什么Redis 深入了解鍵的過期時間redis持久化機制Redis延遲問題全面排障指南一文搞定Redis高級特性與性能調優Redis 在 Linux 系統的配置優化Redis 的延遲問題&…

SpringBoot-lombok

為什么要使用lombok? Lombok是一個通過注解以達到減少代碼的Java庫,如通過注解的方式減少getter,setter方法,構造方法等。通過注解的形式自動生成構造器、getter/setter、equals、hashcode、toString等方法,并可以自動化生成日志變量,簡化java開發、提高…

NLP文本匹配任務Text Matching [有監督訓練]:PointWise(單塔)、DSSM(雙塔)、Sentence BERT(雙塔)項目實踐

NLP文本匹配任務Text Matching [有監督訓練]:PointWise(單塔)、DSSM(雙塔)、Sentence BERT(雙塔)項目實踐 0 背景介紹以及相關概念 本項目對3種常用的文本匹配的方法進行實現:Poin…

pyqt5 如何修改QplainTextEdit 背景色和主窗口的一樣顏色

如果您希望將 QPlainTextEdit 的背景顏色設置為與窗口背景相似的灰色,您可以使用窗口的背景顏色作為基準來設置 QPlainTextEdit 的背景顏色。以下是一個示例代碼,展示如何實現這一點: from PyQt5.QtWidgets import QApplication, QMainWindo…

模型預測筆記(一):數據清洗分析及可視化、模型搭建、模型訓練和預測代碼一體化和對應結果展示(可作為baseline)

模型預測 一、導入關鍵包二、如何載入、分析和保存文件三、修改缺失值3.1 眾數3.2 平均值3.3 中位數3.4 0填充 四、修改異常值4.1 刪除4.2 替換 五、數據繪圖分析5.1 餅狀圖5.1.1 繪制某一特征的數值情況(二分類) 5.2 柱狀圖5.2.1 單特征與目標特征之間的…

Mysql性能優化:什么是索引下推?

導讀 索引下推(index condition pushdown )簡稱ICP,在Mysql5.6的版本上推出,用于優化查詢。 在不使用ICP的情況下,在使用非主鍵索引(又叫普通索引或者二級索引)進行查詢時,存儲引擎…

容斥原理 博弈論(多種Nim游戲解法)

目錄 容斥原理容斥原理的簡介能被整除的數(典型例題)實現思路代碼實現擴展:用DPS實現 博弈論博弈論中的相關性質博弈論的相關結論先手必敗必勝的證明Nim游戲(典型例題)代碼實現 臺階-Nim游戲(典型例題&…

什么叫做云計算

什么叫做云計算 相信大多數人對云計算或者是云服務的認識還停留在僅僅聽過這個名詞,但是對其真正的定義或者意義還不甚了解的層面。甚至有些技術人員,如果日常的業務不涉及到云服務,可能對其也只是一知半解的程度。首先云計算準確的講只是云服…

Java多態詳解(1)

多態 多態的概念 所謂多態,通俗地講,就是多種形態,具體點就是去完成某個行為,當不同的對象去完成時會產生出不同的狀態。 比如: 這一時間爆火的“現代紀錄片”中,麥克阿瑟總是對各種“名人”有不同的評價&…

算法通關村第十關 | 歸并排序

1. 歸并排序原理 歸并排序(MERARE-SORT)簡單來說就是將大的序列先視為若干個比較小的數組,分成比較小的結構,然后是利用歸并的思想實現的排序方法,該算法采用經典的分治策略(分就是將問題分成一些小的問題分…

【Axure模板】APP幫助中心原型,在線客服意見反饋模塊高保真原型

作品概況 頁面數量:共 10 頁 兼容軟件:Axure RP 9/10,不支持低版本 應用領域:原型設計模板 作品申明:頁面內容僅用于功能演示,無實際功能 作品特色 該模板作品為APP幫助與客服的通用模塊,…

golang操作excel的高性能庫——excelize/v2

目錄 介紹文檔與源碼安裝快速開始創建 Excel 文檔讀取 Excel 文檔打開數據流流式寫入 [相關 Excel 開源類庫性能對比](https://xuri.me/excelize/zh-hans/performance.html) 介紹 Excelize是一個純Go編寫的庫,提供了一組功能,允許你向XLAM / XLSM / XLS…

【Kubernetes】Kubernetes的Pod控制器

Pod控制器 一、Pod 控制器的概念1. Pod 控制器及其功用2. Pod 控制器有多種類型2.1 ReplicaSet2.2 Deployment2.3 DaemonSet2.4 StatefulSet2.5 Job2.6 Cronjob 3. Pod 與控制器之間的關系 二、Pod 控制器的使用1. Deployment2. SatefulSet2.1 為什么要有headless?2…

CF113A Grammar Lessons 題解

一道模擬題。 題目傳送門 題目意思: 給你一個句子,讓你檢查這個句子的語法是否正確。(語法請自行在題目中查看) 思路: 就是模擬。依次判斷這個句子是否符合每一條語法即可。但是細節很多就因為細節我錯了好多次&…

數據挖掘 | 零代碼采集房源數據,支持自動翻頁、數據排重等

1 前言 城市規劃、商業選址等應用場景中經常會對地區房價、地域價值進行數據分析,其中地區樓盤房價是分析數據中重要的信息參考點,一些互聯網網站上匯聚了大量房源信息,通過收集此類數據,能夠對地區房價的分析提供參考依據。 如何…

216、仿真-基于51單片機溫度煙霧人體感應布防報警Proteus仿真設計(程序+Proteus仿真+原理圖+配套資料等)

畢設幫助、開題指導、技術解答(有償)見文未 目錄 一、硬件設計 二、設計功能 三、Proteus仿真圖 四、原理圖 五、程序源碼 資料包括: 需要完整的資料可以點擊下面的名片加下我,找我要資源壓縮包的百度網盤下載地址及提取碼。 方案選擇 單片機的選…

SpringBoot 讀取配置文件

Spring Boot 中讀取配置文件有以下 5 種方法: 使用 Value 讀取配置文件。使用 ConfigurationProperties 讀取配置文件。使用 Environment 讀取配置文件。 Autowired private Environment environment; 實現EnvironmentAware接口 使用 PropertySource 讀取配置文件…

Python學習筆記_進階篇(一)_淺析tornado web框架

tornado簡介 1、tornado概述 Tornado就是我們在 FriendFeed 的 Web 服務器及其常用工具的開源版本。Tornado 和現在的主流 Web 服務器框架(包括大多數 Python 的框架)有著明顯的區別:它是非阻塞式服務器,而且速度相當快。得利于…