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ā)揮吧。
第一空,因?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)
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 ;
用?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)