亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

用One-JAR簡化應用程序交付

2019-11-18 11:14:22
字體:
來源:轉載
供稿:網友

  假如您曾經試圖把 java 應用程序交付為單一的 Java 檔案文件(JAR 文件),那么您很有可能碰到過這樣的需求:在構建最終檔案文件之前,要展開支持 JAR 文件(supporting JAR file)。這不但是一個開發的難點,還有可能讓您違反許可協議。在本文中,Tuffs 向您介紹了 One-JAR 這個工具,它使用定制的類裝入器,動態地從可執行 JAR 文件內部的 JAR 文件中裝入類。
  有人曾經說過,歷史總是在不斷地重復自身,首先是悲劇,然后是鬧劇。 最近,我第一次對此有了親身體會。我不得不向客戶交付一個可以運行的 Java 應用程序,但是我已經交付了許多次,它總是布滿了復雜性。在搜集應用程序的所有 JAR 文件、為 DOS 和 Unix(以及 Cygwin)編寫啟動腳本、確??蛻舳谁h境變量都指向正確位置的時候,總是有許多輕易出錯的地方。假如每件事都能做好,那么應用程序能夠按它預期的方式運行。但是在出現麻煩時(而這又是常見的情況),結果就是大量時間耗費在客戶端支持上。
  
  最近與一個被大量 ClassNotFound 異常弄得暈頭轉向的客戶交談之后,我決定自己再也不能忍受下去了。所以,我轉而尋找一個方法,可以把我的應用程序打包到單一 JAR 文件中,給我的客戶提供一個簡單的機制(比如 java -jar)來運行程序。
  
  努力的結果就是 One-JAR,一個非常簡單的軟件打包解決方案,它利用 Java 的定制類裝入器,動態地從單一檔案文件中裝入應用程序所有的類,同時保留支持 JAR 文件的結構。在本文中,我將介紹我開發 One-JAR 的過程,然后告訴您如何利用它在一個自包含的文件中交付您自己的可以運行的應用程序。
  
  One-JAR 概述
  在介紹 One-JAR 的細節之前,請讓我首先討論一下我構建它的目的。我確定一個 One-JAR 檔案文件應該是:
  
  可以用 java -jar 機制執行。
  
  能夠包含應用程序需要的 所有 文件 ―― 也就是說,包括原始形式(未展開)的類和資源。
  
  擁有簡單的內部結構,僅僅用 jar 工具就可以被裝配起來。
  
  對原來的應用程序不可見 ―― 也就是說,無需修改原來的應用程序,就可以把它打包在 One-JAR 檔案文件內部。
  
  問題和解決方案
  在開發 One-JAR 的過程中,我解決的最大問題,就是如何裝入包含在另外一個 JAR 文件中的 JAR 文件。 Java 類裝入器 sun.misc.Launcher$AppClassLoader(在 java -jar 開始的時候出現)只知道如何做兩件事:
  
  裝入在 JAR 文件的根出現的類和資源。
  
  裝入 META-INF/MANIFEST.MF 中的 Class-Path 屬性指向的代碼基中的類和資源。
  而且,它還故意忽略針對 CLASSPATH 的全部環境變量設置,還忽略您提供的命令行參數 -cp 。所以它不知道如何從一個包含在其他 JAR 文件中的 JAR 文件裝入類或資源。
  
  顯然,我需要克服這個問題,才能實現 One-JAR 的目標。
  
  解決方案 1:展開支持 JAR 文件
  我為了創建單一可執行 JAR 文件所做的第一個嘗試,顯然就是在可交付的 JAR 文件內展開支持 JAR 文件,我們把可交付的文件稱為 main.jar。假設有一個應用程序的類叫做 com.main.Main,而且它依靠兩個類 ―― com.a.A (在 a.jar 中) 和 com.b.B(在 b.jar 中),那么 One-JAR 文件看起來應該像這樣:
  
  main.jar
   com/main/Main.class
   com/a/A.class
   com/b/B.class
  
  這樣,最初來源于 a.jar 文件的 A.class 丟失了,B.class 也是如此。雖然這看起來只是個小問題,但卻會真正帶來問題,我很快就會解釋為什么。
  
  One-JAR 和 FJEP
  最近發布的一個叫做 FJEP (FatJar Eclipse Plugin) 的工具支持在 Eclipse 內部直接構建扁平 JAR 文件。 One-JAR 已經與 FatJar 集成在一起,以支持在不展開 JAR 文件的情況下嵌入 JAR 文件。請參閱 參考資料 了解有關具體內容。
  
  把 JAR 文件展開到文件系統以創建一個扁平結構,這可能非常耗時。還需要使用 Ant 這樣的構建工具來展開和重新歸檔支持類。
  
  除了這個小麻煩之外,我很快又碰到了兩個與展開支持 JAR 文件有關的嚴重問題:
  
  假如 a.jar 和 b.jar 包含的資源的路徑名相同 (比如說,都是 log4j.PRoperties ),那么您該選哪個?
  
  假如 b.jar 的許可明確要求您在重新發布它的時候不能修改它,那您怎么辦?您無法在不破壞許可條款的前提下像這樣展開它。
  我覺得這些限制為另外一種方法提供了線索。
  
  解決方案 2: MANIFEST Class-Path
  我決定研究 java -jar 裝入器中的另外一種機制:裝入的類是在檔案文件中一個叫做 META-INF/MANIFEST.MF 的非凡文件中指定的。通過指定稱為 Class-Path 的屬性,我希望能夠向啟動時的類裝入器添加其他檔案文件。下面就是這樣的一個 One-JAR 文件看起來的樣子:
  
  main.jar
   META-INF/MANIFEST.MF
   + Class-Path: lib/a.jar lib/b.jar
   com/main/Main.class
   lib/a.jar
   lib/b.jar
  
  說明與線索
  URLClassloader 是 sun.misc.Launcher$AppClassLoader 的基類,它支持一個相當神秘的 URL 語法,讓您能夠引用 JAR 文件內部的資源。這個語法用起來像這樣: jar:file:/fullpath/main.jar!/a.resource。
  
  從理論上講,要獲得一個在 JAR 文件 內部 的 JAR 文件中的項,您必須使用像 jar:file:/fullpath/main.jar!/lib/a.jar!/a.resource 這樣的方式,但是很不幸,這么做沒有用。JAR 文件協議處理器在找 JAR 文件時,只熟悉最后一個 “!/” 分隔符。
  
  但是,這個語法確實為我最終的 One-JAR 解決方案提供了線索……
  
  這能工作么? 當我把 main.jar 移動到另外一個地方,并試著運行它時,似乎是可以了。為了裝配 main.jar ,我創建了一個名為 lib 的子目錄,并把 a.jar 和 b.jar 放在里面。不幸的是,應用程序的類裝入器只從文件系統提取支持 JAR 文件,而不能從嵌入的 JAR 文件中裝入類。
  
  為了克服這一問題,我試著用神秘的 jar:!/ 語法的幾種變體來使用 Class-Path(請參閱 “說明和線索”),但是沒有一次成功。我能 做的,就只有分別交付 a.jar 和 b.jar ,并把它們與 main.jar 一起放在文件系統中了;但是這正是我想避免的那類事情。
  
  進入 JarClassLoader
  此時,我感到備受挫折。我如何才能讓應用程序從它自己的 JAR 文件中的 lib 目錄裝入它自己的類呢?我決定應當創建定制類裝入器來承擔這個重任。編寫定制類裝入器不是一件輕易的事情。但是實際上這個工作并沒有那么復雜,類裝入器對它所控制的應用程序有非常深刻的影響,所以在發生故障的時候,很難診斷和解釋故障。雖然對于類裝入的完整處理超出了本文的范圍(請參閱 參考資料),我還是要介紹一些基本概念,好保證您能從后面的討論中得到最大收獲。
  
  裝入類
  當 JVM 碰到一個對象的類未知的時候,就會調用類裝入器。類裝入器的工作是找到類的字節碼(基于類的名稱),然后把這些字節傳遞給 JVM,JVM 再把這些字節碼鏈接到系統的其余部分,使得正在運行的代碼可以使用新裝入的類。JDK 中要害的類是 java.lang.Classloader 以及 loadClass 方法,摘要如下:
  
  public abstract class ClassLoader {
  ...
  protected synchronized Class loadClass(String name, boolean resolve)
  throws ClassNotFoundException {...}
  }
  
  ClassLoader 類的主要入口點是 loadClass() 方法。您會注重到, ClassLoader 是一個抽象類,但是它沒有聲明任何抽象方法,這樣,關于 loadClass() 方法是不是要關注的方法,一點線索也沒留下。實際上,它不是 要關注的主方法:回到過去的好時光,看看 JDK 1.1 的類裝入器,可以看到 loadClass() 是您可以有效擴展類裝入器的惟一地方,但是從 JDK 1.2 起,最好讓類裝入器單獨做它所做的工作,即以下工作:
  
  檢查類是否已經裝入。
  檢查上級類裝入器能否裝入類。
  調用 findClass(String name) 方法,讓派生的類裝入器裝入類。
  ClassLoader.findClass() 的實現是拋出一個新的 ClassNotFoundException 異常,并且是我們實現定制類裝入器時要考慮的第一個方法。
  
  JAR 文件何時不是 JAR 文件?
  為了能夠裝入在 JAR 文件內部 的 JAR 文件中的類(這是要害問題,您可以回想起來),我首先必須能夠打開并讀取頂層的 JAR 文件(上面的 main.jar 文件)?,F在,因為我使用的是 java -jar 機制,所以, java.class.path 系統屬性中的第一個(也是惟一一個)元素是 One-JAR 文件的完整路徑名!用下面的代碼您可以得到它:
  
  jarName = System.getProperty("java.class.path");
  
  我接下來的一步是遍歷應用程序的所有 JAR 文件項,并把它們裝入內存,如清單 1 所示:
  
  清單 1. 遍歷查找嵌入的 JAR 文件
  
  JarFile jarFile = new JarFile(jarName);
  Enumeration enum = jarFile.entries();
  while (enum.hasMoreElements()) {
  JarEntry entry = (JarEntry)enum.nextElement();
  if (entry.isDirectory()) continue;
  String jar = entry.getName();
  if (jar.startsWith(LIB_PREFIX) jar.startsWith(MAIN_PREFIX)) {
  // Load it!
  InputStream is = jarFile.getInputStream(entry);
  if (is == null)
  throw new IOException("Unable to load resource /" + jar + " using " + this);
  loadByteCode

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产精品悠悠久久琪琪| 久久免费国产精品1| 亚洲欧美激情精品一区二区| 欧美性猛交99久久久久99按摩| 欧美成人精品三级在线观看| 亚洲成人av片| 午夜免费在线观看精品视频| 精品国偷自产在线视频99| 欧美激情xxxx| 亚洲第一页自拍| 中国人与牲禽动交精品| 色777狠狠综合秋免鲁丝| 亚洲第一区中文99精品| 亚洲精品www久久久| 国产91网红主播在线观看| 日韩亚洲欧美中文在线| 欧美猛少妇色xxxxx| 亚洲第一网中文字幕| 久久久久久有精品国产| 欧美久久久精品| 亚洲欧洲免费视频| 久久伊人精品一区二区三区| 久久亚洲精品国产亚洲老地址| 国产伦精品一区二区三区精品视频| 亚洲自拍小视频| zzijzzij亚洲日本成熟少妇| 日韩精品免费视频| 欧美久久精品一级黑人c片| 中文字幕日韩视频| 日韩精品在线视频美女| 欧美大全免费观看电视剧大泉洋| 国语自产在线不卡| 一本色道久久88综合日韩精品| 国产精欧美一区二区三区| 在线看片第一页欧美| 精品国产电影一区| 亚洲欧美激情精品一区二区| 日韩精品视频在线观看免费| 亚洲欧洲一区二区三区在线观看| 国产一区二区三区网站| 国内精品久久久| 国产精品日韩欧美大师| 成人福利在线视频| 国产一区视频在线播放| 97精品欧美一区二区三区| 91亚洲一区精品| 国产精品美乳一区二区免费| 在线播放国产一区中文字幕剧情欧美| 国产成人精品视频在线| 日本一区二区不卡| 久久高清视频免费| 欧美多人乱p欧美4p久久| 伊人久久男人天堂| 国产精选久久久久久| 国产精品久久久久久av下载红粉| 日韩a**中文字幕| 中文字幕国产亚洲| 国语自产精品视频在免费| 亚洲成人精品视频| 国模精品视频一区二区三区| 成人激情视频在线播放| 国产乱人伦真实精品视频| 国产99久久精品一区二区 夜夜躁日日躁| 在线视频欧美性高潮| www亚洲精品| 亚洲精品视频二区| 亚洲精品一区二区三区婷婷月| 91久久国产精品91久久性色| 91精品国产综合久久香蕉922| 亚洲精品suv精品一区二区| 日韩动漫免费观看电视剧高清| 日韩高清免费观看| 青青久久aⅴ北条麻妃| 久热99视频在线观看| 91久久在线播放| 美女久久久久久久| 国产国语刺激对白av不卡| 2019中文字幕免费视频| 91极品视频在线| 欧美电影免费观看高清| 69视频在线播放| 91精品国产综合久久香蕉最新版| 欧美日韩日本国产| 国内精品久久久久影院优| 亚洲精品小视频在线观看| 国产精品入口日韩视频大尺度| 日韩欧美有码在线| 日韩av网站大全| 九九热r在线视频精品| 亚洲人成电影在线观看天堂色| 热久久99这里有精品| 中文字幕综合在线| 国产日韩欧美综合| 国产精品第七影院| 精品亚洲一区二区| 日韩第一页在线| 韩国福利视频一区| 57pao成人永久免费视频| 国产精品6699| 欧美一级在线亚洲天堂| 一区二区三区在线播放欧美| 亚州av一区二区| 亚洲视频在线观看免费| 国产精品视频区1| 久久亚洲精品一区| 亚洲欧洲在线观看| 中文字幕在线视频日韩| 欧美日韩免费观看中文| 日韩视频―中文字幕| 狠狠爱在线视频一区| 亚洲欧美国产日韩中文字幕| 欧美成人在线免费视频| 国产精品日韩欧美大师| 久久久国产精品亚洲一区| 欧美激情在线观看| 国产在线视频2019最新视频| 色悠悠国产精品| 国产www精品| 91高清免费视频| 精品亚洲国产视频| 日韩av在线免播放器| 日韩精品在线观看一区| 欧美午夜影院在线视频| 欧美日韩一区二区免费在线观看| 久久久久久有精品国产| 久久久久久国产精品美女| 精品久久久久国产| 国产精品久久久久久久久久久久| 欧美日韩国产综合新一区| 久久精品视频在线观看| 亚洲黄色有码视频| 欧美又大粗又爽又黄大片视频| 亚洲一区精品电影| 日本一区二区在线播放| 日韩欧美国产高清91| 国产精品男人爽免费视频1| 91av视频在线观看| 日韩中文综合网| 国产香蕉精品视频一区二区三区| 久久久久久久一区二区| 亚洲综合中文字幕68页| 国产精品视频公开费视频| 亚洲天天在线日亚洲洲精| 国产一区视频在线播放| 欧美福利在线观看| 欧美日韩中文字幕在线| 欧美日韩福利视频| 久久激情五月丁香伊人| 亚洲精品网址在线观看| 日韩精品在线观看一区二区| 欧美日韩美女在线观看| 亚洲综合在线播放| www.日韩欧美| 国产亚洲欧美另类中文| 亚洲美女在线看| 亚洲欧美精品中文字幕在线| 欧美老女人www| 91精品视频在线| 91精品国产综合久久久久久久久| 国外成人免费在线播放| 社区色欧美激情 | 亚洲综合小说区| 亚洲一区二区三区乱码aⅴ蜜桃女| 在线视频日本亚洲性|