欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
用 One-JAR 簡(jiǎn)化應用程序交付
用定制類(lèi)裝入器促進(jìn)編程

級別: 中級

P. Simon Tuffs
獨立顧問(wèn), simontuffs.com
2004 年 11 月 23 日

如果您曾經(jīng)試圖把 Java 應用程序交付為單一的 Java 檔案文件(JAR 文件),那么您很有可能遇到過(guò)這樣的需求:在構建最終檔案文件之前,要展開(kāi)支持 JAR 文件(supporting JAR file)。這不但是一個(gè)開(kāi)發(fā)的難點(diǎn),還有可能讓您違反許可協(xié)議。在本文中,Tuffs 向您介紹了 One-JAR 這個(gè)工具,它使用定制的類(lèi)裝入器,動(dòng)態(tài)地從可執行 JAR 文件內部的 JAR 文件中裝入類(lèi)。

有人曾經(jīng)說(shuō)過(guò),歷史總是在不斷地重復自身,首先是悲劇,然后是鬧劇。 最近,我第一次對此有了親身體會(huì )。我不得不向客戶(hù)交付一個(gè)可以運行的 Java 應用程序,但是我已經(jīng)交付了許多次,它總是充滿(mǎn)了復雜性。在搜集應用程序的所有 JAR 文件、為 DOS 和 Unix(以及 Cygwin)編寫(xiě)啟動(dòng)腳本、確??蛻?hù)端環(huán)境變量都指向正確位置的時(shí)候,總是有許多容易出錯的地方。如果每件事都能做好,那么應用程序能夠按它預期的方式運行。但是在出現麻煩時(shí)(而這又是常見(jiàn)的情況),結果就是大量時(shí)間耗費在客戶(hù)端支持上。

最近與一個(gè)被大量 ClassNotFound 異常弄得暈頭轉向的客戶(hù)交談之后,我決定自己再也不能忍受下去了。所以,我轉而尋找一個(gè)方法,可以把我的應用程序打包到單一 JAR 文件中,給我的客戶(hù)提供一個(gè)簡(jiǎn)單的機制(比如 java -jar)來(lái)運行程序。

努力的結果就是 One-JAR,一個(gè)非常簡(jiǎn)單的軟件打包解決方案,它利用 Java 的定制類(lèi)裝入器,動(dòng)態(tài)地從單一檔案文件中裝入應用程序所有的類(lèi),同時(shí)保留支持 JAR 文件的結構。在本文中,我將介紹我開(kāi)發(fā) One-JAR 的過(guò)程,然后告訴您如何利用它在一個(gè)自包含的文件中交付您自己的可以運行的應用程序。

One-JAR 概述
在介紹 One-JAR 的細節之前,請讓我首先討論一下我構建它的目的。我確定一個(gè) One-JAR 檔案文件應該是:

  • 可以用 java -jar 機制執行。

  • 能夠包含應用程序需要的 所有 文件 —— 也就是說(shuō),包括原始形式(未展開(kāi))的類(lèi)和資源。

  • 擁有簡(jiǎn)單的內部結構,僅僅用 jar 工具就可以被裝配起來(lái)。

  • 對原來(lái)的應用程序不可見(jiàn) —— 也就是說(shuō),無(wú)需修改原來(lái)的應用程序,就可以把它打包在 One-JAR 檔案文件內部。

問(wèn)題和解決方案
在開(kāi)發(fā) One-JAR 的過(guò)程中,我解決的最大問(wèn)題,就是如何裝入包含在另外一個(gè) JAR 文件中的 JAR 文件。 Java 類(lèi)裝入器 sun.misc.Launcher$AppClassLoader(在 java -jar 開(kāi)始的時(shí)候出現)只知道如何做兩件事:

  • 裝入在 JAR 文件的根出現的類(lèi)和資源。

  • 裝入 META-INF/MANIFEST.MF 中的 Class-Path 屬性指向的代碼基中的類(lèi)和資源。

而且,它還故意忽略針對 CLASSPATH 的全部環(huán)境變量設置,還忽略您提供的命令行參數 -cp 。所以它不知道如何從一個(gè)包含在其他 JAR 文件中的 JAR 文件裝入類(lèi)或資源。

顯然,我需要克服這個(gè)問(wèn)題,才能實(shí)現 One-JAR 的目標。

解決方案 1:展開(kāi)支持 JAR 文件
我為了創(chuàng )建單一可執行 JAR 文件所做的第一個(gè)嘗試,顯然就是在可交付的 JAR 文件內展開(kāi)支持 JAR 文件,我們把可交付的文件稱(chēng)為 main.jar。假設有一個(gè)應用程序的類(lèi)叫做 com.main.Main,而且它依賴(lài)兩個(gè)類(lèi) —— com.a.A (在 a.jar 中) 和 com.b.B(在 b.jar 中),那么 One-JAR 文件看起來(lái)應該像這樣:

    main.jar    |  com/main/Main.class    |  com/a/A.class    |  com/b/B.class 			

這樣,最初來(lái)源于 a.jar 文件的 A.class 丟失了, B.class 也是如此。雖然這看起來(lái)只是個(gè)小問(wèn)題,但卻會(huì )真正帶來(lái)問(wèn)題,我很快就會(huì )解釋為什么。

One-JAR 和 FJEP
最近發(fā)布的一個(gè)叫做 FJEP (FatJar Eclipse Plugin) 的工具支持在 Eclipse 內部直接構建扁平 JAR 文件。 One-JAR 已經(jīng)與 FatJar 集成在一起,以支持在不展開(kāi) JAR 文件的情況下嵌入 JAR 文件。請參閱 參考資料 了解有關(guān)詳細內容。

把 JAR 文件展開(kāi)到文件系統以創(chuàng )建一個(gè)扁平結構,這可能非常耗時(shí)。還需要使用 Ant 這樣的構建工具來(lái)展開(kāi)和重新歸檔支持類(lèi)。

除了這個(gè)小麻煩之外,我很快又遇到了兩個(gè)與展開(kāi)支持 JAR 文件有關(guān)的嚴重問(wèn)題:

  • 如果 a.jar 和 b.jar 包含的資源的路徑名相同 (比如說(shuō),都是 log4j.properties ),那么您該選哪個(gè)?

  • 如果 b.jar 的許可明確要求您在重新發(fā)布它的時(shí)候不能修改它,那您怎么辦?您無(wú)法在不破壞許可條款的前提下像這樣展開(kāi)它。

我覺(jué)得這些限制為另外一種方法提供了線(xiàn)索。

解決方案 2: MANIFEST Class-Path
我決定研究 java -jar 裝入器中的另外一種機制:裝入的類(lèi)是在檔案文件中一個(gè)叫做 META-INF/MANIFEST.MF 的特殊文件中指定的。通過(guò)指定稱(chēng)為 Class-Path 的屬性,我希望能夠向啟動(dòng)時(shí)的類(lèi)裝入器添加其他檔案文件。下面就是這樣的一個(gè) One-JAR 文件看起來(lái)的樣子:

    main.jar    |  META-INF/MANIFEST.MF    |  +  Class-Path: lib/a.jar lib/b.jar    |  com/main/Main.class    |  lib/a.jar    |  lib/b.jar     

說(shuō)明與線(xiàn)索
URLClassloadersun.misc.Launcher$AppClassLoader 的基類(lèi),它支持一個(gè)相當神秘的 URL 語(yǔ)法,讓您能夠引用 JAR 文件內部的資源。這個(gè)語(yǔ)法用起來(lái)像這樣: jar:file:/ fullpath/main.jar!/a.resource 。

從理論上講,要獲得一個(gè)在 JAR 文件 內部 的 JAR 文件中的項,您必須使用像 jar:file:/ fullpath/main.jar!/lib/a.jar!/a.resource 這樣的方式,但是很不幸,這么做沒(méi)有用。JAR 文件協(xié)議處理器在找 JAR 文件時(shí),只認識最后一個(gè) “!/” 分隔符。

但是,這個(gè)語(yǔ)法確實(shí)為我最終的 One-JAR 解決方案提供了線(xiàn)索……

這能工作么? 當我把 main.jar 移動(dòng)到另外一個(gè)地方,并試著(zhù)運行它時(shí),好像是可以了。為了裝配 main.jar ,我創(chuàng )建了一個(gè)名為 lib 的子目錄,并把 a.jar 和 b.jar 放在里面。不幸的是,應用程序的類(lèi)裝入器只從文件系統提取支持 JAR 文件,而不能從嵌入的 JAR 文件中裝入類(lèi)。

為了克服這一問(wèn)題,我試著(zhù)用神秘的 jar:!/ 語(yǔ)法的幾種變體來(lái)使用 Class-Path(請參閱 “ 說(shuō)明和線(xiàn)索”),但是沒(méi)有一次成功。我 做的,就只有分別交付 a.jar 和 b.jar ,并把它們與 main.jar 一起放在文件系統中了;但是這正是我想避免的那類(lèi)事情。

進(jìn)入 JarClassLoader
此時(shí),我感到備受挫折。我如何才能讓?xiě)贸绦驈乃约旱?JAR 文件中的 lib 目錄裝入它自己的類(lèi)呢?我決定應當創(chuàng )建定制類(lèi)裝入器來(lái)承擔這個(gè)重任。編寫(xiě)定制類(lèi)裝入器不是一件容易的事情。但是實(shí)際上這個(gè)工作并沒(méi)有那么復雜,類(lèi)裝入器對它所控制的應用程序有非常深刻的影響,所以在發(fā)生故障的時(shí)候,很難診斷和解釋故障。雖然對于類(lèi)裝入的完整處理超出了本文的范圍(請參閱 參考資料),我還是要介紹一些基本概念,好保證您能從后面的討論中得到最大收獲。

裝入類(lèi)
當 JVM 遇到一個(gè)對象的類(lèi)未知的時(shí)候,就會(huì )調用類(lèi)裝入器。類(lèi)裝入器的工作是找到類(lèi)的字節碼(基于類(lèi)的名稱(chēng)),然后把這些字節傳遞給 JVM,JVM 再把這些字節碼鏈接到系統的其余部分,使得正在運行的代碼可以使用新裝入的類(lèi)。JDK 中關(guān)鍵的類(lèi)是 java.lang.Classloader 以及 loadClass 方法,摘要如下:

    public abstract class ClassLoader {        ...        protected synchronized Class loadClass(String name, boolean resolve)            throws ClassNotFoundException {...}    } 			

ClassLoader 類(lèi)的主要入口點(diǎn)是 loadClass() 方法。您會(huì )注意到, ClassLoader 是一個(gè)抽象類(lèi),但是它沒(méi)有聲明任何抽象方法,這樣,關(guān)于 loadClass() 方法是不是要關(guān)注的方法,一點(diǎn)線(xiàn)索也沒(méi)留下。實(shí)際上,它 不是 要關(guān)注的主方法:回到過(guò)去的好時(shí)光,看看 JDK 1.1 的類(lèi)裝入器,可以看到 loadClass() 是您可以有效擴展類(lèi)裝入器的惟一地方,但是從 JDK 1.2 起,最好讓類(lèi)裝入器單獨做它所做的工作,即以下工作:

  • 檢查類(lèi)是否已經(jīng)裝入。
  • 檢查上級類(lèi)裝入器能否裝入類(lèi)。
  • 調用 findClass(String name) 方法,讓派生的類(lèi)裝入器裝入類(lèi)。

ClassLoader.findClass() 的實(shí)現是拋出一個(gè)新的 ClassNotFoundException 異常,并且是我們實(shí)現定制類(lèi)裝入器時(shí)要考慮的第一個(gè)方法。

JAR 文件何時(shí)不是 JAR 文件?
為了能夠裝入在 JAR 文件 內部 的 JAR 文件中的類(lèi)(這是關(guān)鍵問(wèn)題,您可以回想起來(lái)),我首先必須能夠打開(kāi)并讀取頂層的 JAR 文件(上面的 main.jar 文件)?,F在,因為我使用的是 java -jar 機制,所以, java.class.path 系統屬性中的第一個(gè)(也是惟一一個(gè))元素是 One-JAR 文件的完整路徑名!用下面的代碼您可以得到它:

    jarName = System.getProperty("java.class.path");

我接下來(lái)的一步是遍歷應用程序的所有 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(is, jar);	            ...                

注意, LIB_PREFIX 生成字符串 lib/, MAIN_PREFIX 生成字符串 main/。我想把任何以 lib/main/ 開(kāi)始的東西的字節碼裝入內存,供類(lèi)裝入器使用,并在循環(huán)中忽略任何其他 JAR 文件項。

main 目錄
前面我已經(jīng)談到過(guò) lib/ 子目錄的角色,那么 main/ 目錄是干什么的呢?簡(jiǎn)要來(lái)說(shuō),類(lèi)裝入器的代理模式要求我把主要類(lèi) com.main.Main 放在它自己的 JAR 文件中,這樣它才能找到庫類(lèi)(它依賴(lài)的庫類(lèi))。新的 JAR 文件看起來(lái)像這樣:

	one-jar.jar	|  META-INF/MANIFEST.MF	|  main/main.jar	|  lib/a.jar	|  lib/b.jar 

在上面的清單 1 中, loadByteCode() 方法接受來(lái)自 JAR 文件項的流和一個(gè)項名稱(chēng),把項的字節裝入內存,并根據項代表的是 類(lèi) 還是 資源,給它分配最多兩個(gè)名稱(chēng)。演示這個(gè)技術(shù)的最好方法是通過(guò)示例。假設 a.jar 包含一個(gè)類(lèi) A.class 和一個(gè)資源 A.resource。One-JAR 類(lèi)裝入器構造以下 Map 結構,名為 JarClassLoader.byteCode,它對于類(lèi)只有一對關(guān)鍵字/值組合,而對于資源則有兩個(gè)關(guān)鍵字。

圖 1. One-JAR 在內存中的結構

如果您多看圖 1 一會(huì ),您可以看到類(lèi)項是按照類(lèi)名稱(chēng)設置關(guān)鍵字的,而資源關(guān)鍵字的設置則根據一對名稱(chēng):全局名稱(chēng)和局部名稱(chēng)。用來(lái)解析資源名稱(chēng)沖突的機制是:如果兩個(gè)庫 JAR 文件都用相同的全局名稱(chēng)定義一個(gè)資源,那么則根據調用程序的堆棧幀來(lái)采用局部名稱(chēng)。更多細節請參閱 參考資料。

找到類(lèi)
回憶一下,我在概述類(lèi)裝入的時(shí)候,最后介紹的是 findClass() 方法。方法 findClass() 以類(lèi)的名稱(chēng)作為 String 參數,而且必須找到并定義該名稱(chēng)所代表的字節碼。由于 loadByteCode 很好地構建了類(lèi)名和字節碼之間的 Map,所以實(shí)現這個(gè)方法現在非常簡(jiǎn)單:只要根據類(lèi)名查找字節碼,然后調用 defineClass(),如清單 2 所示:

清單 2. findClass() 摘要
    protected Class findClass(String name) throws ClassNotFoundException {        ByteCode bytecode = (ByteCode)JarClassLoader.byteCode.get(name);        if (bytecode != null) {            ...            byte bytes[] = bytecode.bytes;            return defineClass(name, bytes, pd);        }        throw new ClassNotFoundException(name);    }  

裝入資源
在 One-JAR 開(kāi)發(fā)期間, findClass 是我把自己的想法付諸實(shí)施的第一件事。 但是,當我開(kāi)始部署更復雜的應用程序時(shí),我發(fā)現除了要裝入類(lèi)之外,還必須要處理資源的裝入問(wèn)題。這一次,事情有點(diǎn)棘手。為了查找資源,需要在 ClassLoader 中找到一個(gè)合適的方法去覆蓋,我選了我最熟悉的一個(gè),如清單 3 所示:

清單 3. getResourceAsStream() 方法
    public InputStream getResourceAsStream(String name) {        URL url = getResource(name);        try {            return url != null ? url.openStream() : null;        } catch (IOException e) {            return null;        }    }

這個(gè)時(shí)候應當響起警鐘:我就是無(wú)法理解為什么用 URL 來(lái)定位資源。所以我不用這個(gè)實(shí)現,而是插入我自己的實(shí)現,如清單 4 所示:

清單 4. One-JAR 中的 getResourceAsStream() 實(shí)現
    public InputStream getResourceAsStream(String resource) {        byte bytes[] = null;        ByteCode bytecode = (ByteCode)byteCode.get(resource);        if (bytecode != null) {            bytes = bytecode.bytes;         }        ...        if (bytes != null) {            return new ByteArrayInputStream(bytes);        }        ...        return null;    }  

最后一個(gè)障礙
我對 getResourceAsStream() 方法的新實(shí)現看起來(lái)解決了問(wèn)題,但是直到我試著(zhù)用 One-JAR 來(lái)處理一個(gè)用 URL url = object.getClass().getClassLoader().getResource() 模式裝入資源的應用程序時(shí),才發(fā)現實(shí)際情況與想像的不一樣。為什么?因為 ClassLoader 的默認實(shí)現返回的 URL 是 null,這個(gè)結果破壞了調用程序的代碼。

這時(shí),事情變得真的是說(shuō)不清了。我必須弄清應當用什么 URL 來(lái)引用 lib/ 目錄中的 JAR 文件內部的資源。是不是應該像 jar:file:main.jar!lib/a.jar!com.a.A.resource 這樣才好?

我試盡所有我能想到的組合,但是沒(méi)有任何一個(gè)起作用。 jar: 語(yǔ)法就是不支持嵌套 JAR 文件,這使得我的整個(gè) One-JAR 方法好像面臨著(zhù)死路一條。雖然大多數應用程序好像都不使用 ClassLoader.getResource 方法,但是確實(shí)有些使用了這個(gè)方法,所以我實(shí)在不愿意有需要排除的情況,讓我說(shuō)“如果您的應用程序使用 ClassLoader.getResource(),您就不能用 One-JAR。”

最后的解決方案……
當我試圖弄清楚 jar: 語(yǔ)法的時(shí)候,我意外地了解到了 Java 運行時(shí)環(huán)境把 URL 前綴映射到處理器的機制。這成為我修復 findResource 問(wèn)題所需要的線(xiàn)索:我只要發(fā)明自己的協(xié)議前綴,稱(chēng)為 onejar:。這樣,我就能把新的前綴映射到協(xié)議處理器,處理器就會(huì )返回資源的字節流,如清單 5 所示。注意,清單 5 表示的是兩個(gè)文件中的代碼,這兩個(gè)文件是 JarClassLoader 和一個(gè)叫做 com/simontuffs/onejar/Handler.java 的新文件。

清單 5. findResource 和 onejar: 協(xié)議
				        com/simontuffs/onejar/JarClassLoader.java    protected URL findResource(String $resource) {        try {            // resolve($resource) returns the name of a resource in the            // byteCode Map if it is known to this classloader.            String resource = resolve($resource);            if (resource != null) {                // We know how to handle it.                return new URL(Handler.PROTOCOL + ":" + resource);             }            return null;        } catch (MalformedURLException mux) {            WARNING("unable to locate " + $resource + " due to " + mux);        }        return null;    }        com/simontuffs/onejar/Handler.java    package com.simontuffs.onejar;    ...    public class Handler extends URLStreamHandler {        /**         * This protocol name must match the name of the package in which this class         * lives.         */        public static String PROTOCOL = "onejar";        protected int len = PROTOCOL.length()+1;                protected URLConnection openConnection(URL u) throws IOException {            final String resource = u.toString().substring(len);            return new URLConnection(u) {                public void connect() {                }                public InputStream getInputStream() {                    // Use the Boot classloader to get the resource.  There                    // is only one per one-jar.                    JarClassLoader cl = Boot.getClassLoader();                    return cl.getByteStream(resource);                }            };        }    }          

啟動(dòng) JarClassLoader
到現在,您可能只剩下一個(gè)問(wèn)題了:我是怎樣把 JarClassLoader 插入啟動(dòng)順序,讓它首先開(kāi)始從 One-JAR 文件裝入類(lèi)的?具體的細節超出了本文的范圍;但是,基本上說(shuō),我沒(méi)有用主類(lèi) com.main.Main 作為 META-INF/MANIFEST.MF/Main-Class 屬性,而是創(chuàng )建了一個(gè)新的啟動(dòng)主類(lèi) com.simontuffs.onejar.Boot,它被指定作為 Main-Class 屬性。新類(lèi)要做以下工作:

  • 創(chuàng )建新的 JarClassLoader。

  • 用新的裝入器從 main/main.jar 裝入 com.main.Main(基于 main.jar 中的 META-INF/MANIFEST.MF Main-Class 項)。

  • 裝入類(lèi),用反射調用 main(),從而調用 com.main.Main.main(String[]) (或者諸如 main.jar/MANIFEST.MF 文件中的 Main-Class 的名稱(chēng))。在 One-JAR 命令行上傳遞的參數,被不加修改地傳遞到應用程序的主方法。

結束語(yǔ)
如果前面這些讓您頭痛,不要擔心:使用 One-JAR 要比理解它的工作方式容易得多。隨著(zhù) FatJar Eclipse 插件(請參閱 參考資料 中的 FJEP)的推出, Eclipse 的用戶(hù)現在只要在向導中選中一個(gè)復選框,就可以創(chuàng )建 One-JAR 應用程序。依賴(lài)的庫被放進(jìn) lib/ 目錄,主程序和類(lèi)被放進(jìn) main/main.jar,并自動(dòng)寫(xiě)好 META-INF/MANIFEST.MF 文件。如果您使用 JarPlug(還是請參閱 參考資料),您可以查看您構建的 JAR 文件的內部結構,并從 IDE 中啟動(dòng)它。

總之,One-JAR 是一個(gè)簡(jiǎn)單而強大的解決方案,解決了應用程序打包交付的問(wèn)題。但是,它沒(méi)有解決所有的應用程序場(chǎng)景。例如,如果您的應用程序使用老式的 JDK 1.1 的類(lèi)裝入器,不把裝入委托給上一層,那么類(lèi)裝入器就無(wú)法在嵌套 JAR 文件中找到類(lèi)。您可以構建和部署一個(gè)“包裝”類(lèi)裝入器來(lái)修改頑固的類(lèi)裝入器,從而克服這個(gè)問(wèn)題,不過(guò)這可能需要與 Javassist 或者字節碼工程庫(Byte Code Engineering Library,BCEL)這樣的工具一起使用字節碼操縱技術(shù)。

對于嵌入式應用程序和 Web 服務(wù)器使用的特定類(lèi)型的類(lèi)裝入器,您還可能遇到問(wèn)題。特別是對于那些不把裝入工作先委托給上一級的類(lèi)裝入器,以及那些在文件系統中查找代碼基的裝入器,您可能會(huì )碰到問(wèn)題。不過(guò),One-JAR 中包含了一個(gè)機制,可以在文件系統中展開(kāi) JAR 文件項,這應當有幫助。這個(gè)機制由 META-INF/MANIFEST.MF 文件中的 One-JAR-Expand 屬性控制。另外,您可以試著(zhù)用字節碼操縱技術(shù)動(dòng)態(tài)地修改類(lèi)裝入器,這樣可以不破壞支持 JAR 文件的完整性。如果您采用這種方法,那么每種個(gè)別情況可能都需要一個(gè)定制的包裝類(lèi)裝入器。

請參閱 參閱資料 以下載 FatJar Eclipse 插件和 JarPlug,并了解更多關(guān)于 One-JAR 的內容。

參考資料

關(guān)于作者
P. Simon Tuffs 博士是一位獨立顧問(wèn),目前的研究領(lǐng)域是 Java Web 服務(wù)的可伸縮性。在業(yè)余時(shí)間里,他創(chuàng )建并發(fā)布一些開(kāi)源項目,比如 One-JAR。要了解 Tuffs 博士和他的工作,請訪(fǎng)問(wèn) www.simontuffs.com。




本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
精簡(jiǎn)出最小 jre
下面是在 WebLogic 8.1 上配置 Hibernate 的具體步驟
JDK、JRE、JVM之間的關(guān)系
weblucene安裝指南(win2000) - 花嫣然 - 新浪BLOG
AspectJ安裝和配置指南
制作可執行jar文件【3法】
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久