java安全-九游会j9娱乐平台
a. java的安全性體現在哪裡
java最基本的安全性有三個。
第一個就是garbage collection,garbage collector會讓你的程序不容易出現內存泄露。內存泄露是很危險的,在內存泄露的時候黑客可以黑你的電腦。
第二個就是exception,你有沒有發現你想用唄null賦值的東西會出exception?這個就是exception的好處。出現exception的時候程序員可以讓程序停止運行,這樣的話就不會被黑客黑了。
第3個就是指針,java裡面沒有指針!這樣的話人們就不能access不該access的內存了。c的話就非常危險了,黑客可以讓c的程序stack overflow, 然後在overflow的內存地址跳到一個不該跳的地方。
這些就是java裡面的最基本的安全性。
b. 如何調整java安全級別
要在 internet explorer 中配置 java 安全性,請執行以下操作:
啟動 internet explorer,然後單擊工具菜單上的 internet 選項。
在 internet 選項對話框中,單擊安全選項卡。
「安全」頁上有四個安全區域:
選擇要更改其 java 安全性設置的區域。
internet
本地 intranet
受信任的站點
受限制的站點
在該區域的安全級別下,單擊自定義級別。在 internet explorer 4.x 版本中,單擊自定義級別,然後單擊設置。
查看 microsoft vm 部分(internet explorer 4.x 中的 java 部分)。
在 microsoft vm 下的「java 許可權」列表中,單擊自定義。
單擊 java 自定義設置。
單擊查看許可權選項卡可查看當前的 java 許可權。java 許可權分為三種主要類別:
賦予未簽名內容的許可權
請求這些許可權的未簽名 java 小程序無須發出用戶提示便可運行。
允許已簽名內容的許可權
請求這些許可權的已簽名 java 小程序無須發出用戶提示便可運行。
拒絕已簽名內容的許可權
這些許可權拒絕已簽名的 java 小程序。
單擊編輯許可權選項卡。選擇需要用於准確控制該區域 java 許可權的選項。如果不想保留已做出的設置,可以單擊重置按鈕將許可權重置為:
保存的許可權
高安全級
中安全級
低安全級
單擊確定,然後再次單擊確定。
c. 為什麼說java安全性高
java不支持指針, 一切對內存的訪問都必須通過對象的實例變數來實現,這樣就防止程序員使用 "特洛伊"木馬等欺騙手段訪問對象的私有成員,同時也避免了指針操作中容易 產生的錯誤。
最初的java就包括:
禁止運行時堆棧溢出.(例如蠕蟲等病毒常用的襲擊手段);
禁止在自己的處理空間之外破壞內存;
未經授權禁止讀寫文件.
並且,許多安全特性相繼不斷被加入java中.從1.1開始,java就有了數字簽名類(digitally signed class)的概念.(瀏覽網頁時會經常遇到的.)通過數字簽名類,可以確定類的作者.如果信任這個類的作者,這個類在機器上就能擁有更多許可權.
d. 怎麼關閉java 的安全提示
打開java配置項:
兩種方法:①控制面板->java;②開始菜單->java->java配置;
找到高級選項;
往下拉找到「對下列項執行已簽名代碼證書撤銷檢查」;
勾選「不檢查(不推薦)」;
點擊 「確定」/「應用」。
再次運行相關java程序時可能會彈出確認框;
直接勾選「不再對來自以上發行者和位置的應用程序顯示此消息」;
點擊「運行」即可。
以後就不會出現這種的警告了。
高級選項下還有別的限制,這里就不多說了。
備註:
關閉java告警提示有利有弊,好處是程序啟動速度大大加快,而且可以放在開機啟動項裡面隨系統自動啟動;弊端就是不安全,可能會有遠程漏洞被利用。
請自行取捨。
e. java 安全機制是什麼
1.java語言本身嵌入了安全特性,其中包括編譯器/jvm對強數據類型的支持,自動的內存管理,位元組代碼的驗證機制以及獨特的安全類載入方式
2.密碼體系
3.jaas
4.安全通信
5.pki體系
沙箱.jvm
f. java的安全性究竟怎樣體現出來
java的安全性主要體現在:下載到本地的javaapplet只限制在java運行環境中,而不允許它訪問計算機的其他部分。
這是由於java編譯器輸出的並不是可執行代碼,而是位元組代碼(bytecode),java的運行系統就是java虛擬機,每個java程序的運行都是在java虛擬機的控制之下。java虛擬機可以包含這個程序並且阻止它在系統外產生副作用。通過java語言中的適當限制增強了安全性。
g. java中解決安全問題的技術有哪些
對付高嚴重性暴露的技巧
請遵循下列建議以避免高嚴重性靜態安全性暴露:
限制對變數的訪問
讓每個類和方法都成為 final,除非有足夠的理由不這樣做
不要依賴包作用域
使類不可克隆
使類不可序列化
使類不可逆序列化
避免硬編碼敏感數據
查找惡意代碼
限制對變數的訪問
如果將變數聲明為 public,那麼外部代碼就可以操作該變數。這可能會導致安全性暴露。
影響
如果實例變數為 public,那麼就可以在類實例上直接訪問和操作該實例變數。將實例變數聲明為 protected 並不一定能解決這一問題:雖然不可能直接在類實例基礎上訪問這樣的變數,但仍然可以從派生類訪問這個變數。
清單 1 演示了帶有 public 變數的代碼,因為變數為 public 的,所以它暴露了。
清單 1. 帶有 public 變數的代碼
class test {
public int id;
protected string name;
test(){
id = 1;
name = "hello world";
}
//code
}
public class myclass extends test{
public void methodillegalset(string name){
this.name = name; // this should not be allowed
}
public static void main(string[] args){
test obj = new test();
obj.id = 123; // this should not be allowed
myclass mc = new myclass();
mc.methodillegalset("illegal set value");
}
}
建議
一般來說,應該使用取值方法而不是 public 變數。按照具體問題具體對待的原則,在確定哪些變數特別重要因而應該聲明為 private 時,請將編碼的方便程度及成本同安全性需要加以比較。清單 2 演示了以下列方式來使之安全的代碼:
清單 2. 不帶有 public 變數的代碼
class test {
private int id;
private string name;
test(){
id = 1;
name = "hello world";
}
public void setid(int id){
this.id = id;
}
public void setname(string name){
this.name = name;
}
public int getid(){
return id;
}
public string getname(){
return name;
}
}
讓每個類和方法都為 final
不允許擴展的類和方法應該聲明為 final。這樣做防止了系統外的代碼擴展類並修改類的行為。
影響
僅僅將類聲明為非 public 並不能防止攻擊者擴展類,因為仍然可以從它自己的包內訪問該類。
建議
讓每個類和方法都成為 final,除非有足夠的理由不這樣做。按此建議,我們要求您放棄可擴展性,雖然它是使用諸如 java 語言之類的面向對象語言的主要優點之一。在試圖提供安全性時,可擴展性卻成了您的敵人;可擴展性只會為攻擊者提供更多給您帶來麻煩的方法。
不要依賴包作用域
沒有顯式地標注為 public、private 或 protected 的類、方法和變數在它們自己的包內是可訪問的。
影響
如果 java 包不是封閉的,那麼攻擊者就可以向包內引入新類並使用該新類來訪問您想保護的內容。諸如 java.lang 之類的一些包預設是封閉的,一些 jvm 也讓您封閉自己的包。然而,您最好假定包是不封閉的。
建議
從軟體工程觀點來看,包作用域具有重要意義,因為它可以阻止對您想隱藏的內容進行偶然的、無意中的訪問。但不要依靠它來獲取安全性。應該將類、方法和變數顯式標注為 public、private 或 protected 中適合您特定需求的那種。
使類不可克隆
克隆允許繞過構造器而輕易地復制類實例。
影響
即使您沒有有意使類可克隆,外部源仍然可以定義您的類的子類,並使該子類實現 java.lang.cloneable。這就讓攻擊者創建了您的類的新實例。拷貝現有對象的內存映象生成了新的實例;雖然這樣做有時候是生成新對象的可接受方法,但是大多數時候是不可接受的。清單 3 說明了因為可克隆而暴露的代碼:
清單 3. 可克隆代碼
class myclass{
private int id;
private string name;
public myclass(){
id=1;
name="haryporter";
}
public myclass(int id,string name){
this.id=id;
this.name=name;
}
public void display(){
system.out.println("id =" id "
" "name=" name);
}
}
// hackers code to clone the user class
public class hacker extends myclass implements cloneable {
public static void main(string[] args){
hacker hack=new hacker();
try{
myclass o=(myclass)hack.clone();
o.display();
}
catch(clonenotsupportedexception e){
e.printstacktrace();
}
}
}
建議
要防止類被克隆,可以將清單 4 中所示的方法添加到您的類中:
清單 4. 使您的代碼不可克隆
public final object clone()
throws java.lang.clonenotsupportedexception{
throw new java.lang.clonenotsupportedexception();
}
如果想讓您的類可克隆並且您已經考慮了這一選擇的後果,那麼您仍然可以保護您的類。要做到這一點,請在您的類中定義一個為 final 的克隆方法,並讓它依賴於您的一個超類中的一個非 final 克隆方法,如清單 5 中所示:
清單 5. 以安全的方式使您的代碼可克隆
public final object clone()
throws java.lang.clonenotsupportedexception {
super.clone();
}
類中出現 clone() 方法防止攻擊者重新定義您的 clone 方法。
使類不可序列化
序列化允許將類實例中的數據保存在外部文件中。闖入代碼可以克隆或復制實例,然後對它進行序列化。
影響
序列化是令人擔憂的,因為它允許外部源獲取對您的對象的內部狀態的控制。這一外部源可以將您的對象之一序列化成攻擊者隨後可以讀取的位元組數組,這使得攻擊者可以完全審查您的對象的內部狀態,包括您標記為 private 的任何欄位。它也允許攻擊者訪問您引用的任何對象的內部狀態。
建議
要防止類中的對象被序列化,請在類中定義清單 6 中的 writeobject() 方法:
清單 6. 防止對象序列化
private final void writeobject(objectoutputstream out)
throws java.io.notserializableexception {
throw new java.io.notserializableexception("this object cannot
be serialized");
}
通過將 writeobject() 方法聲明為 final,防止了攻擊者覆蓋該方法。
使類不可逆序列化
通過使用逆序列化,攻擊者可以用外部數據或位元組流來實例化類。
影響
不管類是否可以序列化,都可以對它進行逆序列化。外部源可以創建逆序列化成類實例的位元組序列。這種可能為您帶來了大量風險,因為您不能控制逆序列化對象的狀態。請將逆序列化作為您的對象的另一種公共構造器 ? 一種您無法控制的構造器。
建議
要防止對對象的逆序列化,應該在您的類中定義清單 7 中的 readobject() 方法:
清單 7. 防止對象逆序列化
private final void readobject(objectinputstream in)
throws java.io.notserializableexception {
throw new java.io.notserializableexception("this object cannot
be deserialized");
}
通過將該方法聲明為 final,防止了攻擊者覆蓋該方法。
避免硬編碼敏感數據
您可能會嘗試將諸如加密密鑰之類的秘密存放在您的應用程序或庫的代碼。對於你們開發人員來說,這樣做通常會把事情變得更簡單。
影響
任何運行您的代碼的人都可以完全訪問以這種方法存儲的秘密。沒有什麼東西可以防止心懷叵測的程序員或虛擬機窺探您的代碼並了解其秘密。
建議
可以以一種只可被您解密的方式將秘密存儲在您代碼中。在這種情形下,秘密只在於您的代碼所使用的演算法。這樣做沒有多大壞處,但不要洋洋得意,認為這樣做提供了牢固的保護。您可以遮掩您的源代碼或位元組碼 ? 也就是,以一種為了解密必須知道加密格式的方法對源代碼或位元組碼進行加密 ? 但攻擊者極有可能能夠推斷出加密格式,對遮掩的代碼進行逆向工程從而揭露其秘密。
這一問題的一種可能解決方案是:將敏感數據保存在屬性文件中,無論什麼時候需要這些數據,都可以從該文件讀取。如果數據極其敏感,那麼在訪問屬性文件時,您的應用程序應該使用一些加密/解密技術。
查找惡意代碼
從事某個項目的某個心懷叵測的開發人員可能故意引入易受攻擊的代碼,打算日後利用它。這樣的代碼在初始化時可能會啟動一個後台進程,該進程可以為闖入者開後門。它也可以更改一些敏感數據。
這樣的惡意代碼有三類:
類中的 main 方法
定義過且未使用的方法
注釋中的死代碼
影響
入口點程序可能很危險而且有惡意。通常,java 開發人員往往在其類中編寫 main() 方法,這有助於測試單個類的功能。當類從測試轉移到生產環境時,帶有 main() 方法的類就成為了對應用程序的潛在威脅,因為闖入者將它們用作入口點。
請檢查代碼中是否有未使用的方法出現。這些方法在測試期間將會通過所有的安全檢查,因為在代碼中不調用它們 ? 但它們可能含有硬編碼在它們內部的敏感數據(雖然是測試數據)。引入一小段代碼的攻擊者隨後可能調用這樣的方法。
避免最終應用程序中的死代碼(注釋內的代碼)。如果闖入者去掉了對這樣的代碼的注釋,那麼代碼可能會影響系統的功能性。
可以在清單 8 中看到所有三種類型的惡意代碼的示例:
清單 8. 潛在惡意的 java 代碼
public void unusedmethod(){
// code written to harm the system
}
public void usedmethod(){
//unusedmethod(); //code in comment put with bad intentions,
//might affect the system if uncommented
// int x = 100;
// x=x 10; //code in comment, might affect the
//functionality of the system if uncommented
}
建議
應該將(除啟動應用程序的 main() 方法之外的)main() 方法、未使用的方法以及死代碼從應用程序代碼中除去。在軟體交付使用之前,主要開發人員應該對敏感應用程序進行一次全面的代碼評審。應該使用「stub」或「mmy」類代替 main() 方法以測試應用程序的功能。
對付中等嚴重性暴露的技巧
請遵循下列建議以避免中等嚴重性靜態安全性暴露:
不要依賴初始化
不要通過名稱來比較類
不要使用內部類
不要依賴初始化
您可以不運行構造器而分配對象。這些對象使用起來不安全,因為它們不是通過構造器初始化的。
影響
在初始化時驗證對象確保了數據的完整性。
例如,請想像為客戶創建新帳戶的 account 對象。只有在 account 期初余額大於 0 時,才可以開設新帳戶。可以在構造器里執行這樣的驗證。有些人未執行構造器而創建 account 對象,他可能創建了一個具有一些負值的新帳戶,這樣會使系統不一致,容易受到進一步的干預。
建議
在使用對象之前,請檢查對象的初始化過程。要做到這一點,每個類都應該有一個在構造器中設置的私有布爾標志,如清單 9 中的類所示。在每個非 static 方法中,代碼在任何進一步執行之前都應該檢查該標志的值。如果該標志的值為 true,那麼控制應該進一步繼續;否則,控制應該拋出一個例外並停止執行。那些從構造器調用的方法將不會檢查初始化的變數,因為在調用方法時沒有設置標志。因為這些方法並不檢查標志,所以應該將它們聲明為 private 以防止用戶直接訪問它們。
清單 9. 使用布爾標志以檢查初始化過程
public class myclass{
private boolean initialized = false;
//other variables
public myclass (){
//variable initialization
method1();
initialized = true;
}
private void method1(){ //no need to check for initialization variable
//code
}
public void method2(){
try{
if(initialized==true){
//proceed with the business logic
}
else{
throw new exception("illegal state of the object");
}
}catch(exception e){
e.printstacktrace();
}
}
}
如果對象由逆序列化進行初始化,那麼上面討論的驗證機制將難以奏效,因為在該過程中並不調用構造器。在這種情況下,類應該實現 objectinputvalidation 介面:
清單 10. 實現 objectinputvalidation
interface java.io.objectinputvalidation {
public void validateobject() throws invalidobjectexception;
}
所有驗證都應該在 validateobject() 方法中執行。對象還必須調用 objectinputstream.registervalidation() 方法以為逆序列化對象之後的驗證進行注冊。 registervalidation() 的第一個參數是實現 validateobject() 的對象,通常是對對象自身的引用。註:任何實現 validateobject() 的對象都可能充當對象驗證器,但對象通常驗證它自己對其它對象的引用。registervalidation() 的第二個參數是一個確定回調順序的整數優先順序,優先順序數字大的比優先順序數字小的先回調。同一優先順序內的回調順序則不確定。
當對象已逆序列化時,objectinputstream 按照從高到低的優先順序順序調用每個已注冊對象上的 validateobject()。
不要通過名稱來比較類
有時候,您可能需要比較兩個對象的類,以確定它們是否相同;或者,您可能想看看某個對象是否是某個特定類的實例。因為 jvm 可能包括多個具有相同名稱的類(具有相同名稱但卻在不同包內的類),所以您不應該根據名稱來比較類。
影響
如果根據名稱來比較類,您可能無意中將您不希望授予別人的權利授予了闖入者的類,因為闖入者可以定義與您的類同名的類。
例如,請假設您想確定某個對象是否是類 com.bar.foo 的實例。清單 11 演示了完成這一任務的錯誤方法:
清單 11. 比較類的錯誤方法
if(obj.getclass().getname().equals("foo")) // wrong!
// objects class is named foo
}else{
// object's class has some other name
}
建議
在那些非得根據名稱來比較類的情況下,您必須格外小心,必須確保使用了當前類的 classloader 的當前名稱空間,如清單 12 中所示:
清單 12. 比較類的更好方法
if(obj.getclass() == this.getclassloader().loadclass("com.bar.foo")){
// object's class is equal to
//the class that this class calls "com.bar.foo"
}else{
// object's class is not equal to the class that
// this class calls "com.bar.foo"
}
然而,比較類的更好方法是直接比較類對象看它們是否相等。例如,如果您想確定兩個對象 a 和 b 是否屬同一個類,那麼您就應該使用清單 13 中的代碼:
清單 13. 直接比較對象來看它們是否相等
if(a.getclass() == b.getclass()){
// objects have the same class
}else{
// objects have different classes
}
盡可能少用直接名稱比較。
不要使用內部類
java 位元組碼沒有內部類的概念,因為編譯器將內部類轉換成了普通類,而如果沒有將內部類聲明為 private,則同一個包內的任何代碼恰好能訪問該普通類。
影響
因為有這一特性,所以包內的惡意代碼可以訪問這些內部類。如果內部類能夠訪問括起外部類的欄位,那麼情況會變得更糟。可能已經將這些欄位聲明為 private,這樣內部類就被轉換成了獨立類,但當內部類訪問外部類的欄位時,編譯器就將這些欄位從專用(private)的變為在包(package)的作用域內有效的。內部類暴露了已經夠糟糕的了,但更糟糕的是編譯器使您將某些欄位成為 private 的舉動成為徒勞。
建議 如果能夠不使用內部類就不要使用內部類。
對付低嚴重性暴露的技巧
請遵循下列建議以避免低嚴重性靜態安全性暴露:
避免返回可變對象
檢查本機方法
避免返回可變對象
java 方法返回對象引用的副本。如果實際對象是可改變的,那麼使用這樣一個引用調用程序可能會改變它的內容,通常這是我們所不希望見到的。
影響
請考慮這個示例:某個方法返回一個對敏感對象的內部數組的引用,假定該方法的調用程序不改變這些對象。即使數組對象本身是不可改變的,也可以在數組對象以外操作數組的內容,這種操作將反映在返回該數組的對象中。如果該方法返回可改變的對象,那麼事情會變得更糟;外部實體可以改變在那個類中聲明的 public 變數,這種改變將反映在實際對象中。
清單 14 演示了脆弱性。getexposedobj() 方法返回了 exposed 對象的引用副本,該對象是可變的:
清單 14. 返回可變對象的引用副本
class exposed{
private int id;
private string name;
public exposed(){
}
public exposed(int id, string name){
this.id = id;
this.name = name;
}
public int getid(){
return id;
}
public string getname(){
return name;
}
public void setid(int id){
this.id=id;
}
public void setname(string name){
this.name = name;
}
public void display(){
system.out.println("id = " id " name = " name);
}
}
public class exp12{
private exposed exposedobj = new exposed(1,"harry porter");
public exposed getexposedobj(){
return exposedobj; //returns a reference to the object.
}
public static void main(string[] args){
exp12 exp12 = new exp12();
exp12.getexposedobj().display();
exposed exposed = exp12.getexposedobj();
exposed.setid(10);
exposed.setname("hacker");
exp12.getexposedobj().display();
}
}
建議
如果方法返回可改變的對象,但又不希望調用程序改變該對象,請修改該方法使之不返回實際對象而是返回它的副本或克隆。要改正清單 14 中的代碼,請讓它返回 exposed 對象的副本,如清單 15 中所示:
清單 15. 返回可變對象的副本
public exposed getexposedobj(){
return new exposed(exposedobj.getid(),exposedobj.getname());
}
或者,您的代碼也可以返回 exposed 對象的克隆。
檢查本機方法
本機方法是一種 java 方法,其實現是用另一種編程語言編寫的,如 c 或 c 。有些開發人員實現本機方法,這是因為 java 語言即使使用即時(just-in-time)編譯器也比許多編譯過的語言要慢。其它人需要使用本機代碼是為了在 jvm 以外實現特定於平台的功能。
影響
使用本機代碼時,請小心,因為對這些代碼進行驗證是不可能的,而且本機代碼可能潛在地允許 applet 繞過通常的安全性管理器(security manager)和 java 對設備訪問的控制。
建議
如果非得使用本機方法,那麼請檢查這些方法以確定:
它們返回什麼
它們獲取什麼作為參數
它們是否繞過安全性檢查
它們是否是 public、private 等等
它們是否含有繞過包邊界從而繞過包保護的方法調用
結束語
編寫安全 java 代碼是十分困難的,但本文描述了一些可行的實踐來幫您編寫安全 java 代碼。這些建議並不能解決您的所有安全性問題,但它們將減少暴露數目。最佳軟體安全性實踐可以幫助確保軟體正常運行。安全至關重要和高可靠系統設計者總是花費大量精力來分析和跟蹤軟體行為。只有通過將安全性作為至關緊要的系統特性來對待 ? 並且從一開始就將它構建到應用程序中,我們才可以避免亡羊補牢似的、修修補補的安全性方法。
h. java項目中如何實現數據的安全性,比如安全鎖之類的,求代碼
您好,提問者:
1、重要信息進行加密操作。
2、地址欄盡量採用post提交方式。
3、如果涉及多線程的話,可以使用synchronized鎖。
下面例子:
publicclassmain{
publicstaticvoidmain(string[]args){
newthread(newsuo()).start();
newthread(newsuo()).start();
//開啟兩個線程,加鎖之後數據就不會出錯
}
}
classsuoimplementsrunnable{
privatestaticintnum=100;
publicsynchronizedvoidrun(){
while(true){
if(num==0)
break;
else
system.out.println(num--);
}
}
}
i. java的安全性怎麼理解為什麼它是安全的
java適用與網路/分布式環境,因此在安全方面投入了很大精力.使用java可以構建防毒、防篡改的系統.
最初的java就包括:
禁止運行時堆棧溢出.(例如蠕蟲等病毒常用的襲擊手段);
禁止在自己的處理空間之外破壞內存;
未經授權禁止讀寫文件.
並且,許多安全特性相繼不斷被加入java中.從1.1開始,java就有了數字簽名類(digitally signed class)的概念.(我們瀏覽網頁時會經常遇到的.)通過數字簽名類,可以確定類的作者.如果信任這個類的作者,這個類在你機器上就能擁有更多許可權.
但是即使這樣,還是要說一句"安全不是絕對的".
j. java的安全機制有哪些
》類裝載器結構 (class loader)
》class文件檢查器 (the class file verifier)
》內置於java虛擬機(及語言)的安全特性
》安全管理器及java api (security manager)
在java沙箱中,類裝載器體系結構是第一道防線。它在三個方面對java的沙箱起作用:
1>它防止惡意代碼區干涉善意的代碼
2>它守護了被信任的代碼的邊界
3>它將代碼歸於某類(稱為保護域),該類確定了代碼可以進行哪種操作
class文件檢查器:
class文件檢查器保證裝載的class文件內容有正確的內部結構,並且這些class文件互相間協調一致。class文件檢查器實現的安全目標之一就是程序的健壯性。如果某個有漏洞的編譯器,或某個聰明的黑客,產生了一個class文件,而這個class文件中包含了一個方法,則合格方法的位元組碼中含有一條跳轉到方法之外的指令,那麼,一旦這個方法被調用,它將導致虛擬機的崩潰,所以,處於對健壯性的考慮,由虛擬機檢驗它裝載的位元組碼的完整性非常重要。
class文件檢查器要進行四趟獨立的掃描來完成它的操作。
第一趟:class文件的結構檢查
在這一趟掃描中,對每一段將被當做類型導入的位元組序列,class文件檢查器都會確認它是否符合javaclass文件的節本結構。在這一趟檢查中檢查器會進行很多檢查例如:每個class文件都必須以四個同樣的位元組開始:0xcafebabe。因為這個魔數class文件分析器會很容易判斷出某個文件具有明顯問題而加以拒絕。檢查器還必須確認在class文件中聲明的版本號和次版本號,這個版本號必須在這個虛擬機實現可以支持的范圍之內。而且第一趟掃描還必須確認這個class文件有沒有被刪減。總之第一趟掃描的目的就是保證這個位元組序列正確的定義了一個新類型。
第二趟:類型數據的語義檢查
第二趟掃描,檢查器要查看每個組成部分,確認它們是否是其所屬類型的實例,他們的結構是否正確。另外還要檢查這個類本身是否符合特定的條件,它們是由java編程語言規定的。例如,檢查器強制規定除object類以外的類必須有一個超類,或者檢查final類有沒有被子化等。
第三趟:位元組碼驗證
這一趟是要確保採用任何路徑在位元組碼流中都得到一個確定的操作碼,確保操作數棧總是包含正確的數值以及正確的類型。
第四趟:符號引用的驗證
在動態鏈接的過程中,如果包含在一個class文件中的符號引用被解析時,class文件檢查器要進行第四趟檢查。第四趟掃描僅僅是動態鏈接過程的一部分。當一個class文件被裝載時,它包含了對其他類的符號引用以及它們的欄位和方法。一個符號引用是一個字元串,它給出了名字,並且可能還包含了其他關於這個被引用項的信息------這些信息必須足以唯一的識別一個類、方法、欄位。這樣對於其他類的符號引用必須給出這個類的全名;對於其他類的欄位的符號引用必須給出類名、欄位名以及欄位描述符;對於其他類中的方法的引用必須給出類名、方法名以及方法的描述符。
所謂的動態鏈接是一個將符號引用解析為直接引用的過程。
此外,由於java程序是動態鏈接的,所以class文件檢查器在進行第四次掃描中,必須檢查相互引用類之間的兼容性。
除此之外,java虛擬機還有一些內置的安全特性:
》類型安全的引用轉換
》結構化的內存訪問
》自動垃圾收集(不必顯式地釋放被分配的內存)
》空引用檢查
通過保證一個java程序只能使用類型安全的、結構化的方法去訪問內存,java虛擬機使得java程序更為健壯。