JVM從零開始(一)-JVM的類載入、記憶體區域
一、前言
自從入行以來,一直沒有深入學習過JVM,雖然看過好些書、部落格也有一點了解,但都不是專門講JVM的,所以對JVM停留在淺顯的瞭解上,沒有深入瞭解過,一直想深入學習,不過想學的東西太多了,這就導致JVM成了自己的短板,前些日子在網上看到了救火大隊長的《從零開始帶你成為JVM實戰高手》專欄正在更新中,決定藉此機會好好深入學習一下,順便把學習心得結合以前學習的知識記錄下來,加深自己的理解。
二、JVM載入類的過程
- 載入,載入為按需載入,主執行緒需要用到一個類才開始載入一個類。
- 驗證,簡而言之就是校驗class內容是否符合指定規範
- 準備,為類變數分配記憶體空間,並初始預設值。
- 初始化,執行類的初始化程式碼(靜態程式碼塊,靜態賦值程式碼),注:初始化會檢驗父類是否初始化,沒有則必須先初始化父類。
- 使用
- 解除安裝
三、類載入器
種類
- 啟動類載入器-Bootstrap ClassLoader,用於載入Java核心類庫-java安裝目錄下的lib目錄下的class。
- 擴充套件類載入器-Extension ClassLoader,用於載入java下的一些擴充套件類庫-java安裝目錄lib\ext下的class。
- 應用程式類載入器-Application ClassLoader,載入專案ClassPath下所的class。
- 自定義類載入器,自己定義的類載入器
雙親委派機制
意思就是即優先讓父ClassLoader去載入。原因是避免重複載入,保證一個特定classPath下的Class物件在記憶體中的唯一性。
層次圖
tomcat破壞雙親委派
tomcat作為java編碼的web容器,本身也是在jvm中執行,怎麼讓基於tomcat容器的各個web應用正常執行,使得各個web應用包含的應用的class不會亂套,必須破壞雙親委派機制,為每一個web應用的class都用不同的類載入器去載入。
- tomcat的類載入器層次圖
其中:
common、catalina、shared負責載入tomcat自己的核心類庫,webApp載入web應用的class(隔離web應用引用的三方類庫),jsp載入器載入JSP(每個JSP檔案都對應一個Jsp類載入器,jsp載入器支援熱載入,即Jsp只要修改,就重新載入一次覆蓋原來的jsp)。
通過tomcat的類載入機制,可以達成以下目標:
- tomcat支援各個web引用中不同版本的三方類庫相互隔離。
- 同一個第三方類庫的相同版本在不同web應用可以共享。
- tomcat自身依賴的類庫需要與應用依賴的類庫隔離 。
- jsp需要支援修改後不用重啟tomcat即可生效 為了上面類載入隔離和類更新不用重啟,定製開發各種的類載入器。
自定義類載入器的作用
- 實際中,可以從Web伺服器、資料庫或快取伺服器獲取bytes陣列,這就不是系統類載入器能做到的了。
- 可以從不同的路徑中獲取同一個類的不同class物件,可以實現隔離,一個複雜的程式,內部可能按模組組織,不同模組可能使用同一個類,但使用的是不同版本,如果使用同一個類載入器,它們是無法共存的,不同模組使用不同的類載入器就可以實現隔離,Tomcat使用它隔離不同的Web應用,OSGI使用它隔離不同模組。
- 可以實現熱部署。使用同一個ClassLoader,類只會被載入一次,載入後,即使class檔案已經變了,再次載入,得到的也還是原來的Class物件,而使用自定義類載入器,則可以先建立一個新的ClassLoader,再用它載入Class,得到的Class物件就是新的,從而實現動態更新。
四、JVM記憶體區域劃分
方法區(1.8之後叫metaspace-元資料空間)
存放類的元資料資訊,可以理解為反射獲取的Class物件的哪些資訊。
程式計數器
- 記錄當前執行的class檔案中位元組碼指令的位置
- 與執行緒是一對一的關係,每個執行緒都會有自己的一個程式計數器
棧
一個程式計數器對應一個執行緒、一個執行緒對應一個棧、一個棧由一個個棧幀組成,一個方法對應一個棧幀,棧幀包含區域性變量表、運算元棧、動態連結、方法出口(相當於結束方法時需要跳轉的位置)。棧幀在呼叫方法的時候進棧,方法結束的時候出棧。
堆
- 存放引用型別的區域性變數指向的物件的地址
- 所有執行緒共享
- 當引用變數地址資料出棧時,堆中的記憶體釋放由JVM控制回收
其他記憶體區域
- 執行native方法會有執行緒對應的本地方法棧。
- NIO中ByteBuffer類方法:allocateDirect(int capacity)-堆外分配記憶體空間返回DirectBuffer,通過DirectBuffer的Api可以操作堆外記憶體。
圖示
四、小結
這篇文章是JVM總結的第一篇部落格,可能會覺得有點Low,不過寫這篇部落格也是想從零開始學習總結一番,就這樣吧。 文中大部分內容來、圖片(我也自己畫過,但是太醜了,就不貼了)來源於救火大隊長的《從零開始帶你成為JVM實戰高手》專欄文章所學筆記心得,地址在下面,有興趣的朋友可以去看看(是收費專欄,不過較便宜)。
相關推薦
JVM從零開始(一)-JVM的類載入、記憶體區域
一、前言 自從入行以來,一直沒有深入學習過JVM,雖然看過好些書、部落格也有一點了解,但都不是專門講JVM的,所以對JVM停留在淺
JVM從零開始(三)-常用垃圾回收器及原理
一、垃圾回收器有哪些 由於有些年輕代和老年代回收器無法相容,一般使用都是用以下四個組合。 檢視命令 java -XX:+Print
Netty從零開始(一)
需要用到netty,之前就當年實習的時候用過Mina,netty沒用過,所以加急學習了一下,感覺還不錯,不多說,從官網入手,官網地址:http://netty.io/wiki/user-guide-for-4.x.html 有興趣的朋友可以自己去檢視。 前言: 問題 現在
STM32F103+RTT從零開始(一)——點亮LED
最近心血來潮,打算重新撿起老本行,結果發現很多都忘記了。乾脆重新開始學習,並做個從零開始的筆記了。 STM32系列MCU STM32系列晶片包括F0/F1/F2/F3/F4/F7/L0/L1/L4/H7等系列晶片晶片。不同系列的晶片適用於不同的應用場景。
RxJava從零開始(一)
前言:從零開始學習RxJava,首先是現在才來學習確實已經比別人慢了很多了,沒辦法,還是要學呀。RxJava只是響應式程式設計中的一種,還有其他語言的,這些簡介啥的只有去官網看了,響應式程式設計的優點也不說了,我也不想清楚,知道流弊就行了,懂怎麼用,適用於哪些情況再說去研究
《react-native》從零開始(一)生命週期
生命週期,貫穿整個開發過程非常重要。 搭建開發環境 生命週期 react-native 是一種狀態機的模式,和安卓一樣也是存在生命週期的。 先上張經典圖片 如圖,可以把元件生命週期大致分為三個階段: 這裡 我們和android
Git從零開始(三)
16px pop 普通 遠程服務 git clone one img 分享 模式 一、遠程倉庫管理 1、將本地內容推送到遠程庫 先關聯遠程庫,執行命令: git remote add origin https://github.com/Hollydan/gitsto
Kotlin開發基礎從0開始(一)
code ... 多說 lang 學習 function ria lis lac 為什麽學習kotlin kotlin在今年的Google IO 上正式被確認為Android的官方開發語言,想必原因大家也能猜到一二,一是Google與oracle關於Java相關的版權相關的
Hyperledger Fabric 1.0 從零開始(二)——公網環境構建
1.3 項目 htm move 自己 lvm2 fast 情況 tor 1:環境構建 在本文中用到的宿主機環境是Centos ,版本為Centos.x86_647.2,通過Docker 容器來運行Fabric的節點,版本為v1.0。因此,啟動Fabric網絡中的節點需要先安
Hyperledger Fabric 1.0 從零開始(六)——創建Fabric多節點集群
_id 測試 es2017 xtra 去掉 compose 多個 服務 執行命令 4:創建Fabric多節點集群 4.1、配置說明 首先可以根據官方Fabric自帶的e2e_cli列子中的集群方案來生成我們自己的集群,與案例不同的是我們需要把容器都分配到不同的服務器上,彼此
JVM實用參數(一)JVM類型以及編譯器模式
uil 編程 hotspot hashmap 註意 概念 進程 不同 server JVM實用參數(一)JVM類型以及編譯器模式 原文地址:https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-1-j
深入理解JVM虛擬機:(一)Java運行時數據區域
字面量 符號 地方 64位 因此 lower 優化 java堆大小 工作 概述 JVM是Java語言的精髓所在,因為它Java語言實現了跨平臺運行,以及自動內存管理機制等,本文將從概念上介紹JVM內存的各個區域,說明個區域的作用。 JVM運行時數據區模型 Java虛擬機在執
docker從零開始(二)容器初體驗
osi build 技術分享 框架 log 註冊表 代碼 content doc 使用定義容器 Dockerfile Dockerfile定義容器內所需要的環境。對網絡接口和磁盤驅動器等資源的訪問在此環境中進行虛擬化,該環境與系統的其他部分隔離,因此您需要將端口映射到外部
docker從零開始(五)堆棧初體驗,stacks
開始 services 信息 工作 run cer cal tail int 先決條件 安裝Docker 1.13或更高版本。 獲取Docker Compose,請參考第三節 按照第四節中的描述獲取Docker Machine。 在第二節中了解如何創建容器。
Python3從零學習(一)
# python 3.+ # -*- coding: utf-8 -*- #檢視版本號python -V #列印 print("Hello Python") #等待使用者輸入 input("請按下回車鍵") #同一行顯示多條語句 import sys;x = '同一行顯示多條語句';sy
【視訊】Kubernetes1.12從零開始(六):從程式碼編譯到自動部署
作者: 李佶澳 轉載請保留:原文地址 釋出時間:2018/11/10 16:14:00 說明 kubefromscratch-ansible和kubefromscratch介紹 使用前準備
Centos Docker 從零開始(2)之 mssql 的資料庫檔案儲存在主機
Docker mmsql新建資料庫如果能夠把資料庫檔案儲存在主機上就好了,centos好像可以掛載的 docker 的 run 命令: -v ~/nginx/www:/www :將主機中專案的目錄www掛載到容器的/www 準備命令一下: docker run -e
Hyperledger Fabric 1.0 從零開始(五)——執行測試e2e
3:執行測試e2e 3.1、執行fabric-samples的問題說明 該問題說明能夠解決6.1、平臺特定使用的二進位制檔案配置第一步的問題。可以選擇繼續閱讀該說明,或者等參考到6.1小節時再反向閱讀本說明,具體在6.1中會重新指向本步驟。 一般情況下,我們會參照官網來完成第一個網路測試,在該線上文件中會讓我
Hyperledger Fabric 1.0 從零開始(八)——Fabric多節點叢集生產部署
6.1、平臺特定使用的二進位制檔案配置 該方案與Hyperledger Fabric 1.0 從零開始(五)——執行測試e2e類似,根據企業需要,可以控制各節點的域名,及聯盟鏈的統一域名。可以指定單獨節點的訪問,生成指定的公私鑰、證書等檔案。具體的引數配置可以參考generateArtifacts.sh檔案,
【JVM學習筆記】(一)jvm初體驗-記憶體溢位問題分析及解決方案
####1、開始 建立Main類和Demo類,在Main類的main方法中建立List,並向List中無限建立Demo物件,造成記憶體溢位, 並輸出記憶體溢位錯誤檔案在專案目錄下,為了使等待時間減小,設定執行堆記憶體大小。 ####2、建立Demo類 package com.ch