當前位置:首頁 » 編程語言 » java類載入過程

java類載入過程

發布時間: 2022-11-15 04:25:32

java類載入順序

記住 3 條原則:
1、父類優先於子類
2、屬性優先於代碼塊優先於構造方法
3、靜態優先於非靜態
因此,類載入順序為:
父類靜態變數->父類靜態語句塊->子類靜態變數->子類靜態語句塊->父類普通成員變數->父類動態語句塊->父類構造器->子類普通成員變數->子類動態語句塊->子類構造器

Ⅱ java靜態代碼塊 類載入順序問題。

原因就是一句話:先有了父親,才會有兒子!
程序運行時,載入AB兩類,因為A是B子類,所以先載入B類,Load B,再加在A類 LoadA,調用A a = new A()代碼時,會先調用其父類B的構造方法 Create B 再調用A的構造方法 Create A

Ⅲ java運行的五個步驟

Java程序從源文件創建到程序運行要經過兩大步驟:1、源文件由編譯器編譯成位元組碼(ByteCode)
2、位元組碼由java虛擬機解釋運行。因為java程序既要編譯同時也要經過JVM的解釋運行,所以說Java被稱為半解釋語言( "semi-interpreted" language)。
下面通過以下這個java程序,來說明java程序從編譯到最後運行的整個流程。代碼如下:
//MainApp.java
public class MainApp {
public static void main(String[] args) {
Animal animal = new Animal("Puppy");
animal.printName();
}
}
//Animal.java
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void printName() {
System.out.println("Animal ["+name+"]");
}
}
第一步(編譯): 創建完源文件之後,程序會先被編譯為.class文件。Java編譯一個類時,如果這個類所依賴的類還沒有被編譯,編譯器就會先編譯這個被依賴的類,然後引用,否則直接引用,這個有點象make。如果java編譯器在指定目錄下找不到該類所其依賴的類的.class文件或者.java源文件的話,編譯器話報「cant find symbol」的錯誤。

編譯後的位元組碼文件格式主要分為兩部分:常量池和方法位元組碼。常量池記錄的是代碼出現過的所有token(類名,成員變數名等等)以及符號引用(方法引用,成員變數引用等等);方法位元組碼放的是類中各個方法的位元組碼。下面是MainApp.class通過反匯編的結果,我們可以清楚看到.class文件的結構:
第二步(運行):java類運行的過程大概可分為兩個過程:1、類的載入 2、類的執行。需要說明的是:JVM主要在程序第一次主動使用類的時候,才會去載入該類。也就是說,JVM並不是在一開始就把一個程序就所有的類都載入到內存中,而是到不得不用的時候才把它載入進來,而且只載入一次。
下面是程序運行的詳細步驟:
在編譯好java程序得到MainApp.class文件後,在命令行上敲java AppMain。系統就會啟動一個jvm進程,jvm進程從classpath路徑中找到一個名為AppMain.class的二進制文件,將MainApp的類信息載入到運行時數據區的方法區內,這個過程叫做MainApp類的載入。
然後JVM找到AppMain的主函數入口,開始執行main函數。
main函數的第一條命令是Animal animal = new Animal("Puppy");就是讓JVM創建一個Animal對象,但是這時候方法區中沒有Animal類的信息,所以JVM馬上載入Animal類,把Animal類的類型信息放到方法區中。
載入完Animal類之後,Java虛擬機做的第一件事情就是在堆區中為一個新的Animal實例分配內存, 然後調用構造函數初始化Animal實例,這個Animal實例持有著指向方法區的Animal類的類型信息(其中包含有方法表,java動態綁定的底層實現)的引用。
當使用animal.printName()的時候,JVM根據animal引用找到Animal對象,然後根據Animal對象持有的引用定位到方法區中Animal類的類型信息的方法表,獲得printName()函數的位元組碼的地址。
開始運行printName()函數。
特別說明:java類中所有public和protected的實例方法都採用動態綁定機制,所有私有方法、靜態方法、構造器及初始化方法都是採用靜態綁定機制。而使用動態綁定機制的時候會用到方法表,靜態綁定時並不會用到。

Ⅳ java中反射實例類裝載的步驟及簡要闡述

java反射和類裝載

反射機制:

Person p=new Person();
這是什麼?當然是實例化一個對象了.可是這種實例化對象的方法存在一個問題,那就是必須要知道類名才可以實例化它的對象,這樣我們在應用方面就會受到限制.那麼有沒有這樣一種方式,讓我們不知道這個類的類名就可以實例化它的對象呢?Thank Goodness!幸虧我們用的是java, java就提供了這樣的機制.

1).java程序在運行時可以獲得任何一個類的位元組碼信息,包括類的修飾符(public,static等),基類(超類,父類),實現的介面,欄位和方法等信息.
2).java程序在運行時可以根據位元組碼信息來創建該類的實例對象,改變對象的欄位內容和調用對象方法.
這樣的機制就叫反射技術.可以想像光學中的反射,就像我們照鏡子,鏡子中又出現一個自己(比喻可能不太恰當,但是足以表達清楚意思了).反射技術提供了一種通用的動態連接程序組件的方法,不必要把程序所需要的目標類硬編碼到源程序中,從而使得我們可以創建靈活的程序.

反射的實現步驟( 不問不需要答) ,

1、獲取類的常用方式有三種: a) Class.forName("包名.類名"),最常用、推薦;b) 包名.類名.class 最簡捷;c) 對象.getClass 的方式獲得。

2、對象的實例化,上面已經獲取了類,只需要調用類的實例化方法,類.newInstance()便可。

3、獲取屬性和構造等,可以參考 JavaApi 的調用,類. getDeclaredFields,類. getConstructor(..)等。

Java的反射機制是通過反射API來實現的,它允許程序在運行過程中取得任何一個已知名稱的類的內部信息.反射API位於java.lang.reflect包中.主要包括以下幾類:
1).Constructor類:用來描述一個類的構造方法
2).Field類:用來描述一個類的成員變數
3).Method類:用來描述一個類的方法.
4).Modifer類:用來描述類內各元素的修飾符
5).Array:用來對數組進行操作.
Constructor,Field,Method這三個類都是JVM(虛擬機)在程序運行時創建的,用來表示載入類中相應的成員.這三個類都實現了java.lang.reflect.Member介面,Member介面定義了獲取類成員或構造方法等信息的方法.要使用這些反射API,必須先得到要操作的對象或類的Class類的實例.通過調用Class類的newInstance方法(只能調用類的默認構造方法)可以創建類的實例.這樣有局限性,我們可以先沖類的Class實例獲取類需要的構造方法,然後在利用反射來創建類的一個實例.

類載入機制:



類的載入機制可以分為載入-鏈接-初始化三個階段,鏈接又可以分為驗證、准備、解析三個過程。

載入:通過類的載入器查找並載入二進制位元組流的過程,在堆內存中的方法區生成 一個代表這個類的 java.lang.Class 對象,作為這個類的數據請求入口。(這里可以把上面類載入器載入文件的過程描述一下(參考版本一,不作重復))。

驗證:主要是對一些詞法、語法進行規范性校驗,避免對 JVM 本身安全造成危害; 比如對文件格式,位元組碼驗證,無數據驗證等。但驗證階段是非必須的,可以通過參數 設置來進行關閉,以提高載入的時效。

准備:對類變數分配內存,並且對類變數預初始化,初始化成數據類型的原始值, 比如 static int a=11,會被初始化成成 a=0;如果是 static double a =11,則會被初始化成 a=0.0; 而成員變數只會成實例化後的堆中初始化。

解析:把常量池中的符號引用轉換為直接引用的過程。

初始化:對類的靜態變數和靜態塊中的變數進行初始化。(上面的准備階段可以作為 預初始化,初始到變數類型的原值,但如果被 final 修飾會進行真正初始化)

上面載入、鏈接、初始化的各個階段並不是彼此獨立,而是交叉進行,這點很重要 。

***class.forName和 classloader的區別

Class.forName 和 ClassLoader 都是用來裝載類的,對於類的裝載一般為分三個階段載入、鏈接、編譯,它們裝載類的方式是有區別。

首先看一下 Class.forName(..),forName(..)方法有一個重載方法 forName(className,boolean,ClassLoader),它有三個參數,第一個參數是類的包路徑,第二個參數是 boolean

類型,為 true 地表示 Loading 時會進行初始化,第三個就是指定一個載入器;當你調用class.forName(..)時,默認調用的是有三個參數的重載方法,第二個參數默認傳入 true,第三個參數默認使用的是當前類載入時用的載入器。

ClassLoader.loadClass()也有一個重載方法,從源碼中可以看出它默認調的是它的重載 方法 loadClass(name, false),當第二參數為 false 時,說明類載入時不會被鏈接。這也是兩者之間最大區別,前者在載入的時候已經初始化,後者在載入的時候還沒有鏈接。如果你需要在載入時初始化一些東西,就要用 Class.forName 了,比如我們常用的驅動載入, 實際上它的注冊動作就是在載入時的一個靜態塊中完成的。所以它不能被 ClassLoader 載入代替。

Ⅳ Java類載入機制

1,類的載入



每個開發人員對java.lang.ClassNotFoundExcetpion這個異常肯定都不陌生,這背後就涉及到了java技術體系中的類載入。Java的類載入機制是技術體系中比較核心的部分,雖然和大部分開發人員直接打交道不多,但是對其背後的機理有一定理解有助於排查程序中出現的類載入失敗等技術問題,對理解java虛擬機的連接模型和java語言的動態性都有很大幫助。


那麼什麼是類的載入?


類的載入指的是將類的.class文件中的二進制數據讀入到內存中,將其放在運行時數據區的方法區內,然後在堆區創建一個java.lang.Class對象,用來封裝類在方法區內的數據結構。類的載入的最終產品是位於堆區中的Class對象,Class對象封裝了類在方法區內的數據結構,並且向Java程序員提供了訪問方法區內的數據結構的介面。


類載入器是Java語言的一個創新,也是Java語言流行的重要原因之一。它使得Java類可以被動態載入到Java虛擬機中並執行。類載入器從JDK1.0就出現了,最初是為了滿足JavaApplet的需要而開發出來的。JavaApplet需要從遠程下載Java類文件到瀏覽器中並執行。現在類載入器在Web容器和OSGi中得到了廣泛的使用,而類載入器並不需要等到某個類被「首次主動使用」時再載入它,JVM規范允許類載入器在預料某個類將要被使用時就預先載入它,如果在預先載入的過程中遇到了.class文件缺失或存在錯誤,類載入器必須在程序首次主動使用該類時才報告錯誤(LinkageError錯誤)如果這個類一直沒有被程序主動使用,那麼類載入器就不會報告錯誤。


2,類的生命周期


類載入的過程中包括有載入,驗證,准備,解析,初始化五個階段。而需要注意的是在這五個階段中,載入、驗證、准備和初始化這四個階段發生的順序是確定的,而解析階段則不一定,它在某些情況下可以在初始化階段之後開始,這是為了支持Java語言的運行時綁定(也成為動態綁定或晚期綁定)。另外注意這里的幾個階段是按順序開始,而不是按順序進行或完成,因為這些階段通常都是互相交叉地混合進行的,通常在一個階段執行的過程中調用或激活另一個階段。


載入:查找並載入類的二進制數據


載入時類載入過程的第一個階段,在載入階段,虛擬機需要完成以下三件事情:


1、通過一個類的全限定名來獲取其定義的二進制位元組流。(並沒有指明要從一個Class文件中獲取,可以從其他渠道,譬如:網路、動態生成、資料庫等)


2、將這個位元組流所代表的靜態存儲結構轉化為方法區的運行時數據結構。


3、在Java堆中生成一個代表這個類的java.lang.Class對象,作為對方法區中這些數據的訪問入口。


相對於類載入的其他階段而言,載入階段(准確地說,是載入階段獲取類的二進制位元組流的動作)是可控性最強的階段,電腦培訓http://www.kmbdqn.cn/發現因為開發人員既可以使用系統提供的類載入器來完成載入,也可以自定義自己的類載入器來完成載入。


Ⅵ 關於java 類的載入過程,下面哪些描述是正確的

關於Java 類的載入過程,下面哪些描述是正確的(A C )
A、在Java 中,有四種類型的類載入器:BootStrapClassLoader、ExtClassLoader、AppClassLoader 以及用戶自定義的 ClassLoader。
B、使用 new 關鍵字創建類實例時,其實就顯示地包含了類的載入過程
C、在Java 中,類的實例化流程分為兩個部分:類的載入和類的實例化。類的載入又分
為顯式載入和隱式載入。
D、Class.forName 來載入類時,是通過ExtClassLoader進行載入的。

Ⅶ java 類載入先後順序

父類態代碼塊
父類靜態屬性
//以上根據代碼順序
子類靜態屬性
子類靜態代碼塊
//以上根據代碼順序
父類屬性
父類代碼塊
//以上根據代碼順序
父類構造器
子類屬性
子類代碼塊
//以上根據代碼順序
子類構造方法
子類方法
父類方法
父類靜態方法
子類靜態方法

package com.zz;

/**
* Created by @摩西摩西 2020/3/21 22:29
**/
public class Father {
public String name=Son.getmetod("父類屬性");
public Father(){
System.out.println("父類構造器");
}
{
System.out.println("父類代碼塊");
}
public void fatherMethod(){
System.out.println("父類方法");
}

static {
System.out.println("父類態代碼塊");
}
static String name1=Son.getmetod("父類靜態屬性");
public static void fatherStaticMethod(){
System.out.println("父類靜態方法");
}
}
package com.zz;

/**
* Created by @摩西摩西 2020/3/21 22:32
**/
public class Son extends Father {
public String name = getmetod("子類屬性");

public Son() {
System.out.println("子類構造方法");
}

{
System.out.println("子類代碼塊");
}
public void sonMethod(){
System.out.println("子類方法");
}

public static String name1 = getmetod("子類靜態屬性");

static {
System.out.println("子類靜態代碼塊");
}

public static void sonStaticMethod() {
System.out.println("子類靜態方法");
}

public static String getmetod(String s) {
System.out.println(s);
return s;
}

public static void main(String[] args) {
Son son= new Son();
son.sonMethod();
son.fatherMethod();
fatherStaticMethod();
sonStaticMethod();
}
}

Ⅷ 描述一下JVM載入class文件的原理

Java語言是一種具有動態性的解釋型語言,類(class)只有被載入到JVM中後才能運行。當運行指定程序時,JVM會將編譯生成的.class文件按照需求和一定的規則載入到內存中,並組織成為一個完整的Java應用程序。這個載入過程是由類載入器來完成的,具體來說,就是由ClassLoader和它的子類來實現的。類載入器本身也是一個類,其實質是把類文件從硬碟讀取到內存中。
類的載入方式分為隱式載入與顯式載入兩種。隱式載入指的是程序在使用new等方法創建對象時,會隱式地調用類的載入器把對應的類載入到JVM中。顯式載入指的是通過直接調用class.forName()方法來把所需要的類載入到JVM中。
任何一個工程項目都是由許多個類組成的,當程序啟動時,只把需要載入的類載入到JVM中,其他類只有被使用到的時候才會被載入,採用這種方法,一方面可以加快載入速度,另外一方面可以節約程序運行過程中對內存的開銷。此外,在Java語言中,每個類或介面都對應一個.class文件,這些文件可以被看成一個個可以被動態載入的單元,因此當只有部分類被修改時,只需要重新編譯變化的類即可,而不需要重新編譯所有文件,因此加快了編譯速度。

Ⅸ JVM之class載入過程

java虛擬機把描述類的數據從class文件載入到內存,並對數據進行 校驗/准備/解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這個過程被稱作虛擬機的類載入機制。

稱作虛擬機的類載入機制。

loading -> linking (verification -> preparation -> resolution)-> resolution)->initializing

loading: 把class文件load到內存中,採用雙親委派,主要是為了安全性

verification: 校驗class文件是否符合標准

preparation: 靜態變數分配內存並設初始值的階段(不包括實例變數)

resolution:把符號引用轉換為直接引用

initializing:靜態變數賦初始值

類載入的過程主要分為三個部分:載入、連接、初始化這三個階段。

類的載入指的是將類的.class文件中的二進制數據讀入到內存中,將其放在運行時數據區的方法區內,然後在堆區創建一個這個類的java.lang.Class對象,用來封裝類在方法區類的對象。主要步驟可以分為下面的三件事情:

載入階段完成後,虛擬機外部的 二進制位元組流就按照虛擬機所需的格式存儲在方法區之中,而且在Java堆中也創建一個java.lang.Class類的對象,這樣便可以通過該對象訪問方法區中的這些數據。

類的載入的最終產品是位於堆區中的Class對象。Class對象封裝了類在方法區內的數據結構,並且向Java程序員提供了訪問方法區內的數據結構的介面。載入類的方式有以下幾種:

2.載入器

JVM的類載入是通過ClassLoader及其子類來完成的,類的層次關系和載入順序可以由下圖來描述:

1.BootstrapClassLoader(啟動類載入器)

在連接裡面又可以被分成3個小階段,分別是:驗證,准備,解析

1.驗證(目的):

2.驗證內容:

驗證是連接階段的第一步,這一階段的目的是為了確保Class文件的位元組流中包含的信息符合當前虛擬機的要求,並且不會危害虛擬機自身的安全。驗證階段大致會完成4個階段的檢驗動作:

驗證階段是非常重要的,但不是必須的,它對程序運行期沒有影響,如果所引用的類經過反復驗證,那麼可以考慮採用-Xverifynone參數來關閉大部分的類驗證措施,以縮短虛擬機類載入的時間。

3.准備:

在准備階段,為靜態變數的初值為jvm默認的初值,而不是我們在程序中設定的初值。jvm默認為靜態變數的初值是這樣的

4.解析:

這一階段的任務就是把常量池中的符號引用轉換為直接引用 什麼是符號引用,什麼是直接引用。

1.工作內容:

JVM負責主要對類變數(類變數就是static修改的變數)進行初始化這里主要對類變數(類變數就是static修改的變數)進行初始化,初始化主要有兩個方式:

2.初始化時機:

類初始化時機:只有當對類的主動使用的時候才會導致類的初始化,類的主動使用包括以下六種:

3.初始化順序:

如果有父類,則順序是:父類static方法/static變數賦值 –> 子類static方法/static變數賦值

三、結語:

上面介紹的就是類(class)的載入,包含它的載入、鏈接、初始化。
Android進階知識點,我最近整理了許多,裡面講解的非常詳細。取
https://docs.qq.com/doc/DUkNRVFFzTG96VHNiAndroid 技術進階手冊丶面試題綱丶核心筆記資料。

Ⅹ Java中的類是什麼時候被載入到虛擬機

這個問題java的比較核心的一個難題,我就針對問題做簡要回答,不做深入討論了:
1、編譯和運行概念要搞清:編譯即javac的過程,負責將.java文件compile成.class文件,主要是類型、格式檢查與編譯成位元組碼文件,而載入是指java *的過程,將.class文件載入到內存中去解釋執行,即運行的時候才會有載入一說。

2、類的載入時機,肯定是在運行時,但並不是一次性全部載入,而是按需動態,依靠反射來實現動態載入,一般來說一個class只會被載入一次,之後就會從jvm的class實例的緩存中獲取,誰用誰取就可以了,不會再去文件系統中載入.class文件了。

明白1,2點就夠了,再深入要等一段才能明白了。

熱點內容
c語言8位元組 發布:2025-01-13 02:38:51 瀏覽:707
ps3iso文件夾 發布:2025-01-13 02:10:09 瀏覽:290
從qq里如何看到自己的登錄密碼 發布:2025-01-13 02:10:01 瀏覽:432
文明重啟為什麼會有伺服器維護 發布:2025-01-13 02:00:14 瀏覽:353
凈值人群怎麼配置資產 發布:2025-01-13 01:42:07 瀏覽:462
android顯示時間 發布:2025-01-13 01:42:06 瀏覽:4
php微信公眾號開發教程 發布:2025-01-13 01:39:28 瀏覽:191
傳奇攻倍腳本 發布:2025-01-13 01:28:58 瀏覽:511
azure雲先創建資源組還是伺服器 發布:2025-01-13 01:28:25 瀏覽:50
星編程 發布:2025-01-13 01:20:27 瀏覽:451