包含加載java代碼6的詞條

怎樣實(shí)現(xiàn)java代碼的動(dòng)態(tài)加載

1.將你這段字符串輸出到一個(gè)文件里,用Java類文件的方式命名。

創(chuàng)新互聯(lián)建站主要從事網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)常德,十載網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):18982081108

2.調(diào)用外部javac命令將該文件編譯。

3.用類加載器(ClassLoad)動(dòng)態(tài)加載新的class文件并用Class.forName()注冊(cè)該類,然后就可以正常使用了。

上面的每一步都能在baidu中找到實(shí)現(xiàn)方法,自己發(fā)揮吧。

java程序補(bǔ)充,補(bǔ)充6個(gè)代碼

第一空,因?yàn)楸救酥R(shí)不到家,不能根據(jù)你的驅(qū)動(dòng)看出用的哪個(gè)數(shù)據(jù)庫(kù),所以無(wú)法寫。

2.createStatement()

3.select * from 表名

4.executeQuery(sql)

5.long xh = rs.getLong(2)//數(shù)據(jù)類型(要看你第二字段的類型) 變量名=rs.get數(shù)據(jù)類型(2),這個(gè)不是很有把握

6.System.out.println(xh)

怎么 classloader 加載一個(gè)java源文件

1.類加載器深入剖析

Java虛擬機(jī)與程序的生命周期 :

當(dāng)我們執(zhí)行一個(gè)java程序的時(shí)候 , 會(huì)啟動(dòng)一個(gè)JVM進(jìn)程 , 當(dāng)程序執(zhí)行完之后 , JVM進(jìn)程就消亡了 ;

在如下情況下JVM將結(jié)束聲明周期 :

System.exit(int)方法 , 當(dāng)執(zhí)行這個(gè)方法的時(shí)候 , 虛擬機(jī)會(huì)退出 ; 這個(gè)方法傳入一個(gè)整形參數(shù) , 這個(gè)參數(shù)是狀態(tài)嗎 : 如果這個(gè)整形是 0 的話 , 就是正常退出 , 如果不是0的話 , 就是異常退出 ;

程序正常結(jié)束 ;

程序執(zhí)行過程中 , 遇到了異?;蝈e(cuò)誤 , 而異常終止 : 如果我們?cè)诔绦蛑谐霈F(xiàn)了異常 , 而不去處理 , 會(huì)將異常一直拋給main函數(shù) , main函數(shù)會(huì)將異常拋給JVM , JVM如果處理不了異常 , JVM就會(huì)異常退出 ;

由于操作系統(tǒng)出現(xiàn)錯(cuò)誤導(dǎo)致JVM進(jìn)程終止 : JVM所依賴的平臺(tái)出現(xiàn)錯(cuò)誤 , 導(dǎo)致JVM終止 ;

2.類的加載,連接和初始化

加載 : 查找并加載類的二進(jìn)制數(shù)據(jù) , 將class字節(jié)碼文件加載到內(nèi)存中 ;

連接 :

-

驗(yàn)證

: 確保被加載的類的正確性 , 使用javac 編譯工具生成的字節(jié)碼文件能通過驗(yàn)證 , 如果不是由javac編譯生成的字節(jié)碼文件 , 如果自己生成的字節(jié)碼文件不符合JVM虛擬機(jī)對(duì)字節(jié)碼文件的要求的話 , 可能會(huì)出現(xiàn)驗(yàn)證通不過的情況 ; 比如說(shuō)隨便拿一個(gè)文件 , 將后綴名直接修改為.class , 這樣的字節(jié)碼文件肯定不合法 ;

-

準(zhǔn)備

: 為類的靜態(tài)變量分配內(nèi)存 , 并將其初始化為默認(rèn)值 ;

-

解析

: 把類中的符號(hào)引用轉(zhuǎn)為直接引用 ;

初始化 : 為類的靜態(tài)變量賦予正確的初始值(正確的值指的是用戶賦的值) ;

-好像這個(gè)與連接階段的準(zhǔn)備有些重復(fù) , 在連接的準(zhǔn)備階段只是賦予初始變量 , 如果用戶給這個(gè)變量賦了初始值 , 那么這個(gè)變量在連接的準(zhǔn)備階段仍然會(huì)賦予初始值 ;

-在這個(gè)階段 , 才會(huì)真正的將初始值賦給靜態(tài)變量 ;

Java程序?qū)︻惖氖褂梅绞接?主動(dòng)使用 和 被動(dòng)使用 ;

所有的JVM實(shí)現(xiàn) , 必須在每個(gè)類或者接口 , 被java程序 “首次主動(dòng)使用” 時(shí)才初始化他們 ;

主動(dòng)使用 :

創(chuàng)建類的實(shí)例 ;

訪問某個(gè)類或接口的靜態(tài)變量 , 或者對(duì)該靜態(tài)變量賦值 ;

調(diào)用類的靜態(tài)方法 ;

反射 : Class.forName(“類名”) ;

初始化一個(gè)類的子類 , 看做對(duì)父類的主動(dòng)使用 ;

java虛擬機(jī)啟動(dòng)的時(shí)候 , 被標(biāo)明啟動(dòng)類的類 , 即包含main方法的類 , 程序的入口 ;

除了上面6種主動(dòng)使用之外 , 其它的情況均為被動(dòng)使用 , 其它情況都不會(huì)執(zhí)行第三步初始化 ;

3.類的加載

(1)概念

類的加載 : 指的是將類的.class文件中的二進(jìn)制數(shù)據(jù)讀入到內(nèi)存中 , 將其放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)內(nèi) , 然后再堆區(qū)創(chuàng)建一個(gè)java.lang.Class對(duì)象 , 用來(lái)封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu) ;

反射 : 反射就是跟句堆區(qū)的字節(jié)碼文件 , 獲取方法去的數(shù)據(jù)結(jié)構(gòu) ;

解析 : Class對(duì)象是由JVM自己創(chuàng)建的 , 所有的對(duì)象都是經(jīng)過Class對(duì)象創(chuàng)建 , 這個(gè)Class對(duì)象是反射的入口, 通過Class對(duì)象 , 可以關(guān)聯(lián)到目標(biāo)class字節(jié)碼文件的內(nèi)部結(jié)構(gòu) ;

所有的類對(duì)應(yīng)的Class對(duì)象都是唯一的一個(gè) , 這個(gè)類是由JVM進(jìn)行創(chuàng)建的 , 并且只有JVM才會(huì)創(chuàng)建Class對(duì)象 ;

類加載的最終產(chǎn)品是位于堆區(qū)中的Class對(duì)象 , Class對(duì)象封裝了類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu) , 并且向Java程序員提供了訪問方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)的接口(反射用的接口) ;

(2)加載.class文件的方式

從本地系統(tǒng)中直接加載 : 編譯好的.class字節(jié)碼文件直接從硬盤中加載 ;

通過網(wǎng)絡(luò)下載.class文件 : 將class字節(jié)碼文件放在網(wǎng)絡(luò)空間中 , 使用URLClassLoader來(lái)加載在網(wǎng)絡(luò)上的.class字節(jié)碼文件 , 使用默認(rèn)的父親委托機(jī)制加載字節(jié)碼文件 ;

從zip , jar 等壓縮文件中加載字節(jié)碼文件 : 在開發(fā)的時(shí)候 , 導(dǎo)入jar包 , 就是這種方式 ;

從專有的數(shù)據(jù)庫(kù)中提取字節(jié)碼文件 ;

將java源文件動(dòng)態(tài)編譯為字節(jié)碼文件 ;

(3)類加載器

l Java虛擬機(jī)自帶的類加載器 :

-根類加載器 ( Bootstrap ) : 是C++寫的 , 程序員無(wú)法再java代碼中獲取這個(gè)類 , 如果使用getClassLoader()方法獲取到的是一個(gè)null值 ;

package jvm;

Java代碼

public class ClassLoaderTest {

public static void main(String[] args) throws Exception {

//java.lang包下的類使用的是跟類加載器進(jìn)行加載的

Class clazz = Class.forName("java.lang.String");

System.out.println(clazz.getClassLoader());

//自定義的類使用的是應(yīng)用類加載器(系統(tǒng)加載器)

Class clazz2 = Class.forName("jvm.C");

System.out.println(clazz2.getClassLoader());

}

}

class C{}

執(zhí)行結(jié)果 :

null

Java代碼

sun.misc.Launcher$AppClassLoader@1372a1a

-擴(kuò)展類加載器 ( Extension ) : Java編寫 ;

-系統(tǒng)類加載器(應(yīng)用加載器) ( System ) : Java編寫 ;

用戶自定義的類加載器 :

-自定義的類加載器都是java.lang.ClassLoader子類 ;

-用戶可以定制類的加載方式

String類是由根類加載器進(jìn)行加載的 , 我們可以調(diào)用Class對(duì)象的

關(guān)于代理中創(chuàng)建對(duì)象的類加載器 : 創(chuàng)建代理對(duì)象的時(shí)候 , 動(dòng)態(tài)創(chuàng)建一個(gè)類 , 然后使用指定的類加載器將這個(gè)類加載到內(nèi)存中 , 然后用加載到內(nèi)存中的類生成代理對(duì)象 ;

創(chuàng)建代理對(duì)象的方法 : newProxyInstance(ClassLoader loader , Class [] Interfaces , InvocationHandler h )

loader 是定義的代理類的類加載器 , 中間的接口數(shù)組是代理類的要實(shí)現(xiàn)的接口列表 , h 是指派方法調(diào)用的調(diào)用處理程序 ;

類加載器并不需要在某個(gè)類被 “首次主動(dòng)使用” 時(shí)再加載它 :

-預(yù)加載機(jī)制 : JVM規(guī)范允許類加載器在預(yù)料某個(gè)類將要被使用的時(shí)就預(yù)先加載它 ;

-報(bào)錯(cuò)時(shí)機(jī) : 如果在預(yù)加載的過程中遇到了字節(jié)碼文件缺失或者存在錯(cuò)誤的情況 , 類加載器會(huì)在程序首次主動(dòng)使用(上面提到的六種情況)該類的時(shí)候報(bào)錯(cuò)(LinkageError錯(cuò)誤) ;

-不報(bào)錯(cuò)時(shí)機(jī) : 如果這個(gè)錯(cuò)誤的字節(jié)碼文件所對(duì)應(yīng)的類一直沒有被使用 , 那么類加載器就不會(huì)報(bào)告錯(cuò)誤 ,即便有錯(cuò)誤也不會(huì)報(bào)錯(cuò) ;

LinkageError : 這個(gè)錯(cuò)誤是Error的子類 , 程序不能處理這些錯(cuò)誤 , 這些錯(cuò)誤都是由虛擬機(jī)來(lái)處理 , 這個(gè)錯(cuò)誤表示出錯(cuò)的是子類 , 在一定程序上依賴于另一個(gè)類 , 在編譯了前面一個(gè)類的時(shí)候 , 與后面所依賴的類出現(xiàn)了不兼容的情況 ;

例如 : 我們使用了jdk 1.6 在編譯一個(gè)程序 , 但是運(yùn)行環(huán)境是jre1.5的 , 就會(huì)出現(xiàn)LinkageError錯(cuò)誤 ;

4.類的連接

(1)定義

類被加載之后 , 就進(jìn)入鏈接階段 ; 鏈接 : 將已讀入內(nèi)存的二進(jìn)制數(shù)據(jù)合并到虛擬機(jī)的運(yùn)行時(shí)環(huán)境中去 ;

鏈接顧名思義就是講類與類之間進(jìn)行關(guān)聯(lián) , 例如我們?cè)陬怉中調(diào)用了類B , 在鏈接過程中 , 就將A與B進(jìn)行鏈接 ,將面向?qū)ο笳Z(yǔ)言轉(zhuǎn)化為面向過程語(yǔ)言 ;

(2)類的驗(yàn)證

類文件的結(jié)構(gòu)檢查 : 確保類文件遵從java類文件的固定格式 , 開始類的描述 , 聲明 , 方法調(diào)用格式等 ;

語(yǔ)義檢查 : 確保類本身符合java語(yǔ)言的語(yǔ)法規(guī)定 , 比如final類型的類沒有子類 , final類型的方法沒有被覆蓋 ,在eclipse中這種錯(cuò)誤編譯的時(shí)候不能通過 , 但是通過其他的方法可以生成錯(cuò)誤的字節(jié)碼文件 , 這里就是檢測(cè)惡意生成的字節(jié)碼文件 ;

字節(jié)碼驗(yàn)證 : 確保字節(jié)碼流可以被JVM安全的執(zhí)行 , 字節(jié)碼流代表java方法(包括靜態(tài)方法和實(shí)例方法) , 它是由被稱作操作碼的單字節(jié)指令組成的序列 , 每一個(gè)操作碼后面跟著一個(gè)或多個(gè)操作數(shù) , 字節(jié)碼驗(yàn)證步驟會(huì)檢查每個(gè)操作碼是否合法 , 即是否有著合法的操作數(shù) ;

下面是指令碼組成的序列 , 類似于微指令 :

Jvm編譯指令代碼代碼

// Compiled from ByteToCharCp1122.java (version 1.5 : 49.0, super bit)

public class sun.io.ByteToCharCp1122 extends sun.io.ByteToCharSingleByte {

// Field descriptor #17 Lsun/nio/cs/ext/IBM1122;

private static final sun.nio.cs.ext.IBM1122 nioCoder;

// Method descriptor #18 ()Ljava/lang/String;

// Stack: 1, Locals: 1

public java.lang.String getCharacterEncoding();

0 ldc String "Cp1122" [1]

2 areturn

Line numbers:

[pc: 0, line: 25]

// Method descriptor #2 ()V

// Stack: 2, Locals: 1

public ByteToCharCp1122();

0 aload_0 [this]

1 invokespecial sun.io.ByteToCharSingleByte() [25]

4 aload_0 [this]

5 getstatic sun.io.ByteToCharCp1122.nioCoder : sun.nio.cs.ext.IBM1122 [23]

8 invokevirtual sun.nio.cs.ext.IBM1122.getDecoderSingleByteMappings() : java.lang.String [27]

11 putfield sun.io.ByteToCharSingleByte.byteToCharTable : java.lang.String [24]

14 return

Line numbers:

[pc: 0, line: 28]

[pc: 4, line: 29]

[pc: 14, line: 30]

// Method descriptor #2 ()V

// Stack: 2, Locals: 0

static {};

0 new sun.nio.cs.ext.IBM1122 [15]

3 dup

4 invokespecial sun.nio.cs.ext.IBM1122() [26]

7 putstatic sun.io.ByteToCharCp1122.nioCoder : sun.nio.cs.ext.IBM1122 [23]

10 return

Line numbers:

[pc: 0, line: 22]

}

l 二進(jìn)制兼容性的驗(yàn)證 : 確保相互引用的類之間協(xié)調(diào)一致的 ; 例如在A類的a()方法中調(diào)用B類的b()方法 , JVM在驗(yàn)證A類的時(shí)候 , 會(huì)驗(yàn)證B類的b()方法 , 加入b()方法不存在 , 或者版本不兼容(A,B兩類使用不同的JDK版本編譯) , 會(huì)拋出NoSuchMethodError錯(cuò)誤 ;

(3)準(zhǔn)備階段

在準(zhǔn)備階段 , JVM為類的靜態(tài)變量分配內(nèi)存空間 , 并設(shè)置默認(rèn)的初始值 . 例如下面的Sample類 , 在準(zhǔn)備階段 ,為int類型的靜態(tài)變量分配4個(gè)字節(jié) , 并賦予初始值 0 ; 為long 類型的靜態(tài)變量 b , 分配8個(gè)字節(jié) , 并賦予初始值 0 ;

PS : 在java中基本類型變量占用的空間是一定的 , java運(yùn)行在JVM上的 , 在C中 , 就要根據(jù)平臺(tái)變化而變化了 ;

public class Sample {

Java代碼

private static int a = 1 ;

private static long b ;

static {

b = 2 ;

}

(4)類的解析

在解析階段 , JVM 會(huì)把類的二進(jìn)制數(shù)據(jù)中的符號(hào)引用替換為直接引用 , 例如在A類中的a()方法引用B類中的b()方法 ;

在A類的二進(jìn)制數(shù)據(jù)中包含了一個(gè)對(duì)B類的b()方法的符號(hào)引用 , 這個(gè)符號(hào)引用由b()方法的全名和相關(guān)的描述符組成 , 在Java解析階段 , 就會(huì)把這個(gè)符號(hào)引用替換為指針 , 這個(gè)指針就是C語(yǔ)言中的指針了 , 該指針指向B類的b()方法在方法區(qū)中的內(nèi)存位置 , 這個(gè)指針就是直接引用 ;

5.類的初始化

在初始化階段 , Java虛擬機(jī)執(zhí)行類的初始化操作 , 為類的靜態(tài)變量賦予初始值 , 在程序中 , 靜態(tài)變量初始化有兩種途徑 :

直接在聲明處進(jìn)行初始化 , 例如下面的Sample中的 變量a ;

在靜態(tài)代碼塊中進(jìn)行初始化 , 例如下面的Sample中的變量b ;

Java代碼

public class Sample {

private static int a = 1 ;

private static long b ;

static {

b = 2 ;

}

}

6.面試題介紹

Java代碼

public class PrepareOrInit {

public static void main(String[] args) {

Singleton singleton = Singleton.getInstance();

System.out.println(singleton.count1);

System.out.println(singleton.count2);

}

}

class Singleton{

private static Singleton singleton = new Singleton() ;

public static int count1 ;

public static int count2 = 0 ;

private Singleton(){

count1 ++ ;

count2 ++ ;

}

public static Singleton getInstance(){

return singleton ;

}

}

執(zhí)行結(jié)果 : 1 0

分析 : 這段代碼與類的鏈接中的準(zhǔn)備階段 和 初始化階段 有關(guān)系 , 準(zhǔn)備階段是給靜態(tài)的字段賦予默認(rèn)值 , 初始化階段給靜態(tài)變量賦予正確的值 , 即用戶的值 ;

在主函數(shù)中 , 調(diào)用了類的靜態(tài)方法 , 相當(dāng)于主動(dòng)使用 , 這里調(diào)用了類的靜態(tài)方法 ;

之后進(jìn)行連接的準(zhǔn)備操作 , 給類中的靜態(tài)變量賦予初值 , singleton值為null , count1 與 count2 值為0 ;

執(zhí)行初始化操作 , 給類中的靜態(tài)變量賦予正確的值 , 給singleton變量賦予正確的值 , 調(diào)用構(gòu)造方法 , 此時(shí)count1與 count2執(zhí)行自增操作 , 兩者都變成1 , 然后執(zhí)行count1的賦予正確值操作 , 這里用戶沒有賦值操作 , count2 用戶進(jìn)行了 賦值為0的操作 , 0將原來(lái)的1覆蓋掉了 , 因此結(jié)果為 1 , 0 ;

Java代碼

public class PrepareOrInit {

public static void main(String[] args) {

Singleton singleton = Singleton.getInstance();

System.out.println(singleton.count1);

System.out.println(singleton.count2);

}

}

class Singleton{

public static int count1 ;

public static int count2 = 0 ;

private static Singleton singleton = new Singleton() ;

private Singleton(){

count1 ++ ;

count2 ++ ;

}

public static Singleton getInstance(){

return singleton ;

}

}

執(zhí)行結(jié)果 : 1 1

在準(zhǔn)備階段count1 和 count2 都賦值為0 , 然后在初始化階段 , 全部賦值為1 ;

在看jdbc時(shí),書上說(shuō)java6支持驅(qū)動(dòng)程序自動(dòng)加載,也就是不用Class.forName顯示加載

用?WinRAR?或?WinZip?打開?那個(gè)?JDBC?4.0+?的驅(qū)動(dòng)程序,(早期版本的驅(qū)動(dòng)程序是不支持的),你可以看到?META-INF?文件夾下面多出了一個(gè)文件,它里面寫著驅(qū)動(dòng)程序的名字。JDBC??DriverManager?會(huì)自動(dòng)搜索??META-INF/xxxxx?去嘗試讀取它找到的任何?jar?中的這個(gè)目錄,如果有東西就會(huì)自動(dòng)?Class.forName?加載它,這在?Java?中叫?Service?Provider?discovery?機(jī)制,自動(dòng)發(fā)現(xiàn),JSP?中的?tld?文件也是使用類似的機(jī)制,以前需要我們手工把它們配置在 web.xml ?里面,后來(lái)不需要了,你可以找一個(gè)?jstl.jar?打開來(lái)看看,設(shè)計(jì)原理是一樣的。以后你可以模仿一樣,在?META-INF?中添加一個(gè)東西來(lái)當(dāng)然插件機(jī)制。掃描 META-INF 也可能由 JVM 自動(dòng)來(lái)完成并添加它到 System.getProperties() 里面。

如圖:

本文標(biāo)題:包含加載java代碼6的詞條
本文鏈接:http://muchs.cn/article14/hcijge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、響應(yīng)式網(wǎng)站、網(wǎng)站建設(shè)網(wǎng)站導(dǎo)航、域名注冊(cè)、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)