1. 程式人生 > >JVM從零開始(一)-JVM的類載入、記憶體區域

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