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