Java在加载阶段会加载依赖吗,Java程序编译和运行过程之 一个对象的生命之旅(类加载和类加载器)...
Java程序從創(chuàng)建到運行要經(jīng)過兩個大步驟
1:源文件(.java)由編譯器編譯成字節(jié)碼ByteCode(.class)
2:字節(jié)碼由Java虛擬機解釋并運行
源文件編譯成字節(jié)碼,主要分成兩個部分:
1:常量池:所有的Token(類名、成員變量名等)、符號的引用(方法引用、成員變量應(yīng)用等)
2:方法字節(jié)碼:各個類中的各個方法的字節(jié)碼
字節(jié)碼由Java虛擬機解析運行分成兩個部分:
1:類加載
2:類的執(zhí)行
程序運行的詳細步驟:(運行一個對象下的方法內(nèi)部的細節(jié))
Animal.java
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void printName() {
System.out.println("Animal ["+name+"]");
}
}
MainApp.java
public class MainApp {
public static void main(String[] args) {
Animal animal = new Animal("Puppy");
animal.printName();
}
}
下面是程序運行的詳細步驟:
1. 在編譯好java程序得到MainApp.class文件后,執(zhí)行MainApp。
系統(tǒng)就會啟動一個jvm進程,jvm進程從classpath路徑中找到一個名為MainApp.class的二進制文件,將MainApp的類信息加載到運行時數(shù)據(jù)區(qū)的方法區(qū)內(nèi),這個過程叫做MainApp類的加載。
2. JVM找到AppMain的主函數(shù)入口,開始執(zhí)行main函數(shù)。
3. main函數(shù)的第一條命令是Animal animal = new Animal("Puppy");
就是讓JVM創(chuàng)建一個Animal對象,但是這時候方法區(qū)中沒有Animal類的信息,所以JVM馬上加載Animal類,把Animal類的類型信息放到方法區(qū)中。
4. 加載完Animal類之后,Java虛擬機做的第一件事情就是在堆區(qū)中為一個新的Animal實例分配內(nèi)存, 然后調(diào)用構(gòu)造函數(shù)初始化Animal實例,這個Animal實例持有著指向方法區(qū)的Animal類的類型信息(其中包含有方法表,java動態(tài)綁定的底層實現(xiàn))的引用。
5. 當使用animal.printName()的時候,JVM根據(jù)animal引用找到Animal對象,然后根據(jù)Animal對象持有的引用定位到方法區(qū)中Animal類的類型信息的方法表,獲得printName()函數(shù)的字節(jié)碼的地址。
6. 開始運行printName()函數(shù)。
類加載
類的加載指的是將類的.class文件中的二進制數(shù)據(jù)讀入到內(nèi)存中,將其放在運行時數(shù)據(jù)區(qū)的方法區(qū)內(nèi),然后在堆區(qū)創(chuàng)建一個java.lang.Class對象,用來封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)。
類的加載的最終產(chǎn)品是位于堆區(qū)中的Class對象,Class對象封裝了類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu),并且向Java程序員提供了訪問方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)的接口
類加載機制的內(nèi)部細節(jié)
從類被加載到虛擬機內(nèi)存中開始,到卸御出內(nèi)存為止,它的整個生命周期分為7個階段:
加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸御(Unloading)。其中驗證、準備、解析三個部分統(tǒng)稱為連接。 7個階段發(fā)生的順序如下:
加載
1、將class文件加載在內(nèi)存中。
2、將靜態(tài)數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)存在于class文件的結(jié)構(gòu))轉(zhuǎn)化成方法區(qū)中運行時的數(shù)據(jù)結(jié)構(gòu)。
注意:方法區(qū)中如果出現(xiàn)OOM,那么多半是因為加載的依賴太多
3、在堆中生成一個代表這個類的java.lang.Class對象,作為數(shù)據(jù)訪問的入口
連接
1、驗證:確保加載的類符合JVM規(guī)范與安全。保證被校驗類的方法在運行時不會做出危害虛擬機安全的事件
2、準備:為static變量在方法區(qū)中分配空間,設(shè)置變量的初始值。例如static int a=3,在此階段會a被初始化為0;
注意:準備階段,只設(shè)置類中的靜態(tài)變量(方法區(qū)中),不包括實例變量(堆內(nèi)存中),實例變量是在對象初始化的時候分配值的
3、解析:
解析階段是虛擬機將常量池內(nèi)的符號引用替換為直接引用的過程。
符號引用:簡單的理解就是字符串,比如引用一個類,java.util.ArrayList 這就是一個符號引用
直接引用:指針或者地址偏移量。引用對象一定在內(nèi)存(已經(jīng)加載)。
初始化
初始化是類加載的最后階段,初始化階段是執(zhí)行類構(gòu)造器()方法。在類構(gòu)造器方法中,它將**由編譯器自動收集類中的所有類變量的賦值動作**()和靜態(tài)變量與靜態(tài)語句塊static{}合并
**初始化,為類的靜態(tài)變量賦予正確的初始值**
使用、卸載
使用:正常使用
卸載:GC把無用的對象從內(nèi)存中卸載
類加載器
其中加載、驗證、準備、解析、初始化構(gòu)成了類加載的的整個過程;
但是類的加載是需要通過類加載器來實現(xiàn)的
1)Bootstrap ClassLoader
負責加載$JAVA_HOME中jre/lib/rt.jar里所有的 class,由 C++ 實現(xiàn),不是 ClassLoader 子類。
2)Extension ClassLoader
負責加載Java平臺中擴展功能的一些 jar 包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目錄下的 jar 包。
3)App ClassLoader
負責加載 classpath 中指定的 jar 包及目錄中 class。
4)Custom ClassLoader
屬于應(yīng)用程序根據(jù)自身需要自定義的 ClassLoader,如 Tomcat、jboss 都會根據(jù) J2EE 規(guī)范自行實現(xiàn) ClassLoader。
加載過程中會先檢查類是否被已加載,檢查順序是自底向上,從 Custom ClassLoader 到 BootStrap ClassLoader 逐層檢查,只要某個 Classloader 已加載就視為已加載此類,保證此類只所有 ClassLoader 加載一次。而加載的順序是自頂向下,也就是由上層來逐層嘗試加載此類。
通過代碼驗證類加載器模型:
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
System.out.println(loader);
System.out.println(loader.getParent());
System.out.println(loader.getParent().getParent());
}
}
在獲取ExtClassLoader的父loader的時候出現(xiàn)了null,這是因為Bootstrap Loader(引導類加載器)是用C++語言實現(xiàn)的,找不到一個確定的返回父Loader的方式,于是就返回null
java 程序編譯和運行過程
java整個編譯以及運行的過程相當繁瑣,我就舉一個簡單的例子說明: Java程序從源文件創(chuàng)建到程序運行要經(jīng)過兩大步驟: 1.源文件由編譯器編譯成字節(jié)碼(ByteCode): 2.字節(jié)碼由java虛擬機 ...
Java程序編譯和運行的過程
Java整個編譯以及運行的過程相當繁瑣,本文通過一個簡單的程序來簡單的說明整個流程. 如下圖,Java程序從源文件創(chuàng)建到程序運行要經(jīng)過兩大步驟:1.源文件由編譯器編譯成字節(jié)碼(ByteCode) ?2 ...
Java程序編譯和運行的過程【轉(zhuǎn)】
轉(zhuǎn)自:http://www.360doc.com/content/14/0218/23/9440338_353675002.shtml Java整個編譯以及運行的過程相當繁瑣,本文通過一個簡單的程序來 ...
.NET概念:.NET程序編譯和運行
.NET概念:.NET程序編譯和運行 分類: c#程序設(shè)計 2012-02-29 15:46 3001人閱讀 評論(2) 收藏 舉報 .net編譯器語言microsoftassemblyvb.net ...
Java編輯編譯及運行環(huán)境
Java編輯編譯及運行環(huán)境 Microsoft Windows 編輯工具 EditPlus JDK JDK(Java Development Kit,Java開發(fā)工具包)安裝JDK之后,其中bin文件 ...
Java高編譯低運行錯誤(ConcurrentHashMap.keySet)
Java高編譯低運行錯誤(ConcurrentHashMap.keySet) 調(diào)了一天: https://www.jianshu.com/p/f4996b1ccf2f
.NET程序編譯和運行
一次面試的時候遇到的一道題目,簡要說明.NET的編譯過程,在網(wǎng)上看了很多資料,簡單總結(jié)如下: 1.一般的編譯過程 通常高級語言的程序編譯過程是:首先寫好的程序是源代碼,然后編譯器編譯為本地機器語言,最 ...
java程序可以跨平臺運行的原因
java有虛擬機(JVM),JAVA程序不是直接在電腦上運行的,是在虛擬機上進行的,每個系統(tǒng)平臺都是有自己的虛擬機(JVM),所以JAVA語言能跨平臺. 1, java代碼不是直接運行在CPU上,而是 ...
java文件編譯及運行
1 配置環(huán)境變量 使用鼠標右擊“我的電腦”->屬性->高級->環(huán)境變量 系統(tǒng)變量->新建->變量名:JAVA_HOME 變量值:C:\Program Files (x86 ...
隨機推薦
c#導出bugfree3.0的數(shù)據(jù)到禪道
環(huán)境:vs2012MVC4項目,mysql server5.6 準備:bugfree的數(shù)據(jù)庫導出后.sql文件,禪道7.1的數(shù)據(jù)庫文件 基本過程:這是個笨辦法,也沒有優(yōu)化過代碼,導入數(shù)據(jù)時候比較慢.禪 ...
用Python向MySQL數(shù)據(jù)庫插入數(shù)據(jù)
最近一直在學習MySQL數(shù)據(jù)庫,很感興趣.這次我做了一個簡單的嘗試,使用Python3.4與MySQL數(shù)據(jù)庫進行交互,將一份從雪球網(wǎng)上下載的某股票數(shù)據(jù)上傳至MySQL數(shù)據(jù)庫.僅為初學者提供參考,高手請 ...
ruby Errors &; Exceptions
When you first started coding, errors were probably the last thing you wanted to see. After all, it’ ...
【Shell腳本學習4】幾種常見的Shell
上面提到過,Shell是一種腳本語言,那么,就必須有解釋器來執(zhí)行這些腳本. Unix/Linux上常見的Shell腳本解釋器有bash.sh.csh.ksh等,習慣上把它們稱作一種Shell.我們常說 ...
servlet跳轉(zhuǎn)jsp
ackage?com.monkey.servlet; import?javax.servlet.*; import?javax.servlet.http.*; import?java.io.*; im ...
關(guān)于iOS應(yīng)用管理之九宮格的坐標計算以及與UIScrollView的結(jié)合
關(guān)于九宮格的布局以及坐標的計算,對于大多數(shù)的iOS初學者甚至有一定能力的學者來說都是一大難題,在此寫者通過自己的開發(fā)經(jīng)驗以及多次應(yīng)用,把自己的所學所得分享給大家,就通過應(yīng)用管理來進行淺談一二. ? ? ...
RMSE、RMS、標準差
1.均方根誤差,它是觀測值與真值偏差的平方和觀測次數(shù)n比值的平方根,在實際測量中,觀測次數(shù)n總是有限的,真值只能用最可信賴(最佳)值來代替.方根誤差對一組測量中的特大或特小誤差反映非常敏感,所以,均方 ...
【開發(fā)技術(shù)】對文件內(nèi)容進行加密-java
http://hi.baidu.com/java0804ms/item/111ea834fbd4d2f596f88d5a 實現(xiàn)效果:對文件內(nèi)容進行加密,使之直接打開成為亂碼,不以明文顯示 實現(xiàn)步驟:1 ...
python3隨機數(shù)函數(shù)
隨機數(shù)函數(shù) choice(seq) 從序列的元素中隨機挑選一個元素,比如random.choice(range(10)),從0到9中隨機挑選一個整數(shù). randrange ([start,] stop ...
Spring系列__01HelloWorld
Spring作為一款成熟的Java框架,其優(yōu)點和意義不用我多說,可以參考:https://m.w3cschool.cn/wkspring/pesy1icl.html 今天開始寫一下Spring家族的總 ...
總結(jié)
以上是生活随笔為你收集整理的Java在加载阶段会加载依赖吗,Java程序编译和运行过程之 一个对象的生命之旅(类加载和类加载器)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php yii 插入,YII框架批量插入
- 下一篇: 用户类java,通过Java中的类和接口