熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

關於 java.exe 是如何載入 JVM

2013-11-23 18:56:50  來源: Java核心技術 

  將會生成如下個項目
  HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit
  HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Plugin
  HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
  
  同時Java SDK安裝程序將會把javaexejavawexejavaregexe這個可執行文件拷貝到winnt\system目錄下由於winnt\system被操作系統缺省的設置為最高優先權的PATH搜索路徑因此可保證用戶在命令行任何目錄下可運行javaexe來啟動JVM
  
  那麼javaexe在啟動時如何確定其JRE所在的目錄以及需要動態加載的鏈接庫呢?javaexe是通過下面方式來確定的
  
  假如存在/jre/bin/javadll文件則查找/jre/lib/ jvmcfg文件在該文件中個被列出的jvmdll類型作為缺省值(假如在javaexe命令行指定了jvmdll的類型則使用指定類型)jvmdll類型分為hotspotclassicserver三種假如不存在/jre/lib/jvmcfg文件則打印下面的錯誤信息
  
  Error: could not open c:\jdk\jre\lib\jvmcfg
  
  如不存在/jre/bin/javadll(當運行的是winnt\system\javaexe)則注冊表將在此時發揮作用HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\ CurrentVersion鍵值所記錄的實際上是winnt\system\javaexe的版本值該版本值只保存主次兩個版本號
  
  同時javaexe程序內部本身也有一個標識自身的版本值javaexe根據自己內部的版本值和CurrentVersion值相比較如果發現兩個值相等則將在HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\MainVersionMicroVersion項下獲取JRE所在目錄及動態鏈接庫這兩個鍵的名稱分別是JavaHome和RuntimeLibMainVersion表示主版本號MicroVersion表示次版本號
  
  如果javaexe內部版本值和CurrentVersion不一致則報類似以下的錯誤
  
  Registry key Software\JavaSoft\Java Runtime Environment\CurrentVersion
  has value but is required
  
  意思是說注冊表當前所記載的winnt\system\javaexe版本為但是此時運行的javaexe版本為javaexe抱怨除非注冊表有版的記載否則自己無法正確定位JRE目錄和jvmdll因此提示是需要的
  
  這裡我們不能簡單的修改注冊表的CurrentVersion值來達到這個目的一般地當在系統中裝了兩套版本的Java SDK(如先裝而後又裝了後面安裝的Java SDK會將自己帶的javaexe和javawexe拷貝到winnt\system目錄下從而覆蓋先前版本的javaexe和javawexe並且在注冊表中改寫CurrentVersion為所以建議在安裝Java SDK前先卸載以前安裝的版本如果人為的修改CurrentVersion會使得不同版本的javaexe加載與己版本不符的javadll及jvmdll將引起難以預料的後果!
  
  特殊情況
  JBuilder自己帶一套JDK在JBuilder安裝完成後JBuilder安裝程序會修改CurrentVersion為自己所帶JDK的版本但不會覆蓋winnt\system下的javaexe和javawexe
  
  WebLogic自己帶一套JDK在WebLogic安裝完成後WebLogic安裝程序不會修改注冊表也不會覆蓋winnt\system下的javaexe和javawexe
  
  Oracle自己帶一套JDK(一般是比較低版本的例如僅僅帶JDK 在Oracle安裝完成後Oracle安裝程序不會修改注冊表也不會覆蓋winnt\system下的javaexe和javawexe但是Oralce安裝程序會修改系統PATH變量將自帶的JRE的bin路徑加入其中且置於最前面隨著Oracle安裝版本的不同其自帶JRE的JVM啟動程序也不同在筆者機器上安裝的Oracle 其JRE就裝在C:\Program Files\Oracle下並將C:\Program Files\Oracle\jre\\bin放在PATH變量最前其JVM啟動程序是jreexe而非javaexe
  
  以上就是Java SDK在Windows下安裝時所做的動作這樣會帶來兼容性問題
  
  問題背景安裝Java SDK後安裝了JBuilder未修改任何PATH變量
  
  問題
  當在操作系統中安裝了JDK 其後安裝了JBuilder(自帶JDK 這時CurrentVersion為在命令行執行java version時提示
  
  Registry key Software\JavaSoft\Java Runtime Environment\CurrentVersion
  has value but is required
  
  解決方法將JDK 中javaexe所在路徑加入到操作系統PATH的首位從而保證在命令行調用java時總是執行JDK 中的javaexe以使得javaexe可正確定位JRE和jvmdll
  
  問題
  當在操作系統中安裝了JDK 而後安裝了JBuilder(自帶JDK 這時CurrentVersion為但是此是指向的是JBuilder自帶的JDK 的JRE而非指向先前JDK 的JRE當在命令行執行java version時此時執行的是JDK 拷貝到winnt\system的一個javaexe副本但打印的版本信息卻是
  
  java version
  Java(TM) Runtime Environment Standard Edition (build b)
  Java HotSpot(TM) Client VM (build b mixed mode)
  
  導致該問題的原因是javaexe只維護小數點後位的版本號而非
  
  解決方法同問題
  問題
  如果在操作系統中先安裝了JDK 而後安裝了帶有與安裝JDK主次版本相同的JBuilder(帶JDK 前兩位相同)則問題實際上被隱蔽了沒有發生的機會而問題的隱蔽性也很強不容易發覺因為人們往往會忽略JDK的第個版本號
  
  如問題所敘在命令行執行java雖然是使用JDK 的一個javaexe副本(winnt\system目錄下)而實際上卻是使用JBuilder下JDK 的JRE及其目錄結構其結果是當我們使用Java的extension mechanism將jar文件放到JDK 的jre\lib\ext目錄下時發現達不到希望的效果 – 在命令行用java啟動程序時不會自動去JDK 的jre\lib\ext目錄下去搜索jar文件它只會去JBuilder下JDK 的jre\lib\ext去搜索jar文件而JBuilder下的JDK 並不存在jre\lib\ext這麼一個目錄!
  
  問題極為隱蔽除非完全對Java SDK的安裝及class定位機制了解一般的開發者是難以發現問題所在的有關Java中class定位機制見《Java中的class定位機制》一文
  
  事實上即使僅僅在系統中存在一份JDK 如果在命令行運行java的話使用的JRE目錄是C:\Program Files\JavaSoft\JRE\也就是說即使我們在c:\jdk\jre\lib\ext下放置我們的extension jar也得不到預期的結果正確的做法是放在C:\Program Files\JavaSoft\JRE\\lib\ext目錄下
  
  解決方法同問題
  綜上所敘強烈建議將%JDK_HOME%\bin目錄放在Windows操作系統的PATH變量的首位以避免潛在的問題
  
  而在UNIX下則完全不存在類似Windows操作系統上的問題
  
  我們在命令下執行的java是/bin/java
  
  $which java
  $/bin/java
  
  而/bin是到/usr/bin的鏈接也就是說/bin/java實際上是/usr/bin/java
  
  而/usr/bin/java實際上鏈接到/usr/java/bin/java/usr/java是到/usr/java的鏈接(Solaris 或更高系統內置JDK 所以我們實際上執行的java是
  
  /usr/java/bin/java
  
  根據UNIX上的情況java在運行時實際上總是可以用/jre/lib/sparc/libjavaso和/jre/lib/sparc/libjvmso來找到這個文件前者類似於Windows下的javadll而後者類似於Windows下的jvmdll所以java也總是可以確定自己JRE的目錄
  
  Windows和UNIX上用到的動態鏈接庫實際上在Sun的文檔中稱為optional packages native code binariesoptional pakage實際上即為extension mechanism classes詳見《Java中的class定位機制》
  
  要更改UNIX上java的版本更改/usr/java的鏈接是其中一個方法具體可參見JDK在UNIX上的安裝介紹
  
  補充
  
  Windows如何定位Plugin
  
  根據在PATH環境變量中找到的javaexe的版本號到HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Plugin下尋找對應版本的Java Plugin在HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Plugin下可以有多個版本的Plugin存在
  
  不依賴HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit的CurrentVersion值和HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment的CurrentVersion值來定位應該使用哪個版本的Java Plugin
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26028.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.