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

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

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

開(kāi)通VIP
在舊版 JVM 上使用 J2SE 5.0 特性

如果試圖在早期的 JVM 上運行J2SE 5.0 生成的代碼,將會(huì )得到 java.lang.UnsupportedClassVersionError 錯誤。開(kāi)放源代碼的 Retroweaver 項目可以消除 JDK 5.0 (Set JDK Compliance = 5.0) 編譯器限制.Retroweaver 使用 classworking 技術(shù)來(lái)修改由 JDK 5.0 編譯器生成的二進(jìn)制類(lèi)表示,以便這些類(lèi)可以與早期的 JVM (e.g j2sdk1.4.2) 一起使用。


Retroweaver 包含兩個(gè)邏輯組件:一個(gè)字節碼增強器和一個(gè)運行時(shí)庫。字節碼增強器使用 classworking 技術(shù)來(lái)修改由 JDK 5.0 編譯器生成的類(lèi)文件,使得這些類(lèi)可以用于舊版 JVM。作為類(lèi)文件修改的一部分,Retroweaver 可能需要替換對添加到 J2SE 5.0 中的標準類(lèi)的引用。實(shí)際的替換類(lèi)包含在運行時(shí)庫中,以便在您執行修改過(guò)的代碼時(shí)它們是可用的。

按照標準開(kāi)發(fā)周期來(lái)說(shuō),字節碼增強器需要在 Java 代碼編譯之后、類(lèi)文件為部署而打包之前運行。在您使用一個(gè) IDE 時(shí),該更改是一個(gè)問(wèn)題 ——“集成”一個(gè)類(lèi)轉換工具到“開(kāi)發(fā)環(huán)境”是很痛苦的事情,因為 IDE 一般假設它們擁有類(lèi)文件。限制這一痛苦的一種方式是,只對 IDE 中的大多數測試使用 JDK 5.0。這樣,您只需要在想要為部署打包文件或者想要測試實(shí)際的部署 JVM 時(shí)轉換類(lèi)文件。如果使用 Ant 風(fēng)格的構建過(guò)程,就沒(méi)有問(wèn)題;只添加 Retroweaver 字節碼增強器作為編譯之后的一個(gè)步驟。

Retroweaver 具有一個(gè)小小的限制:它并不支持也包含在 J2SE 5.0 中的所有添加到標準 Java 類(lèi)的特性。如果您的代碼使用任何添加到 J2SE 5.0 中的類(lèi)或方法,那么就將在試圖加載舊版 JVM 中的代碼時(shí)得到錯誤,哪怕是在 Retroweaver 處理完成之后也如此。


J2SE 5.0 的更改既發(fā)生在 JVM 中,也發(fā)生在實(shí)際的 Java 語(yǔ)言,但是 JVM 更改相當小。有一個(gè)新的字符可以用于字節碼中的標識符中 ("+"),一些處理類(lèi)引用的指令發(fā)生了修改,還有一個(gè)不同的方法用于處理合成組件。 Retroweaver 在字節碼增強步驟中處理這些 JVM 更改,方法是把這些更改返回原樣,即替換成用于 J2SE 5.0 之前相同目的的方法(比如標識符中的 + 字符,就是用 $ 取代它)。

包含在 J2SE 5.0 中的語(yǔ)言更改要稍微復雜一點(diǎn)。一些最有趣的更改,比如增強的 for 循環(huán),基本上只是語(yǔ)法更改,即為表示編程操作提供快捷方式。比如泛型更改 —— 泛型類(lèi)型信息 —— 由編譯器用于實(shí)施編譯時(shí)安全,但是生成的字節碼仍然到處使用強制轉換。但是大多數更改使用了添加到核心 Java API 中的類(lèi)或方法,所以您不能直接使用為 JDK 5.0 生成的字節碼并將它直接運行在早期的 JVM 上。Retroweaver 為支持 J2SE 5.0 語(yǔ)言更改所需的新類(lèi)提供其自己的等價(jià)物,并且用對其自己的類(lèi)的引用替換對標準類(lèi)的引用,這是字節碼增強步驟的一部分。

Retroweaver 字節碼增強不能對所有的 J2SE 5.0 語(yǔ)言更改提供完全支持。例如,沒(méi)有對處理注釋的運行時(shí)支持,因為運行時(shí)支持涉及到對基本 JVM 類(lèi)加載器實(shí)現的更改。但是一般來(lái)說(shuō),只是不支持那些不會(huì )影響普通用戶(hù)的小特性。

Retroweaver 發(fā)揮作用
使用 Retroweaver 簡(jiǎn)直是太容易了??梢允褂靡粋€(gè)簡(jiǎn)單的 GUI 界面或者控制臺應用程序來(lái)在應用程序類(lèi)文件上運行字節碼增強。兩種方式都只要在將要轉換的類(lèi)文件樹(shù)的根目錄指出 Retroweaver 即可。在運行時(shí),如果使用任何需要運行時(shí)支持的特性(比如 enums),那么就需要在類(lèi)路徑中包含 Retroweaver 運行時(shí) jar。

清單 1. 簡(jiǎn)單的 J2SE 5.0 enum 示例
package com.sosnoski.dwct;public enum Primitive{    BOOLEAN, BYTE, CHARACTER, DOUBLE, FLOAT, INT, LONG, SHORT;        public static void main(String[] args) {        for (Primitive p : Primitive.values()) {            int size = -1;            switch (p) {                case BOOLEAN:                case BYTE:                    size = 1;                    break;                case CHARACTER:                case SHORT:                    size = 2;                    break;                case FLOAT:                case INT:                    size = 4;                    break;                case DOUBLE:                case LONG:                    size = 8;                    break;            }            System.out.println(p + " is size " + size);        }    }}

使用 JDK 5.0 編譯并運行清單 1 代碼會(huì )給出清單 2 中的輸出。但是不能在早期的 JDK 下編譯或運行清單 1 代碼;由于特定于 J2SE 5.0 的特性會(huì )導致編譯失敗,而運行失敗會(huì )拋出 java.lang.UnsupportedClassVersionError 異常。

清單 2. enum 示例輸出
[dennis@notebook code]$ java -cp classes com.sosnoski.dwct.PrimitiveBOOLEAN is size 1BYTE is size 1CHARACTER is size 2DOUBLE is size 8FLOAT is size 4INT is size 4LONG is size 8SHORT is size 2

清單 3 展示了在 Primitive 類(lèi)上運行 Retroweaver。這個(gè)類(lèi)實(shí)際上編譯為兩個(gè)類(lèi)文件,一個(gè)用于 enum 類(lèi),另一個(gè)支持在 switch 語(yǔ)句中使用 enum。(注意,清單代碼換行是為了適應頁(yè)面寬度。)

清單 3. enum 示例輸出
[dennis@notebook code]$ java -cp retro/release/retroweaver.jar:retro/lib/bcel-5.1.jar:retro/lib/  jace.jar:retro/lib/Regex.jar com.rc.retroweaver.Weaver -source classes[RetroWeaver] Weaving /home/dennis/writing/articles/devworks/series/may05/code/  classes/com/sosnoski/dwct/Primitive$1.class[RetroWeaver] Weaving /home/dennis/writing/articles/devworks/series/may05/code/  classes/com/sosnoski/dwct/Primitive.class

在運行 Retroweaver 之后,這些類(lèi)就可以用于 JDK 5.0 和 JDK 1.4 JVM 上了。當使用 1.4 JVM 運行修改后的類(lèi)時(shí),輸出與 清單 2 中的相同。Retroweaver 提供命令行選項來(lái)指定舊的 1.3 和 1.2 JVM 以取代默認的 1.4 目標,但是我下載的運行時(shí) jar 版本需要 1.4,我不想重新構建它以檢查對早期 JVM 的支持。


我用于對 JDK 5.0 實(shí)現 toString() 方法生成的 com.sosnoski.asm.ToStringAgent 類(lèi)對于舊版 JVM 有一個(gè)小小的問(wèn)題:它使用 J2SE 5.0 中新增的 instrumentation API 來(lái)在運行時(shí)截取類(lèi)加載和修改類(lèi)。在早期 JVM 中截取類(lèi)加載不太靈活,但是并不是不可能 —— 只需要用您自己的版本來(lái)取代用于應用程序的類(lèi)加載器就可以了。由于所有的應用程序類(lèi)都是通過(guò)您的自定義類(lèi)加載器加載的,所以在它們被實(shí)際提供給 JVM 之前,您可以自由地修改類(lèi)表示。

清單 4. ToStringLoader 代碼
package com.sosnoski.asm;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader;import org.objectweb.asm.ClassReader;import org.objectweb.asm.ClassWriter;public class ToStringLoader extends URLClassLoader{    private ToStringLoader(URL[] urls, ClassLoader parent) {        super(urls, parent);    }    // override of ClassLoader method    protected Class findClass(String name) throws ClassNotFoundException {        String resname = name.replace(‘.‘, ‘/‘) + ".class";        InputStream is = getResourceAsStream(resname);        if (is == null) {            System.err.println("Unable to load class " + name +                " for annotation checking");            return super.findClass(name);        } else {            System.out.println("Processing class " + name);            try {                                // read the entire content into byte array                ByteArrayOutputStream bos = new ByteArrayOutputStream();                byte[] buff = new byte[1024];                int length;                while ((length = is.read(buff)) >= 0) {                    bos.write(buff, 0, length);                }                byte[] bytes = bos.toByteArray();                                // scan class binary format to find fields for toString() method                ClassReader creader = new ClassReader(bytes);                FieldCollector visitor = new FieldCollector();                creader.accept(visitor, true);                FieldInfo[] fields = visitor.getFields();                if (fields.length > 0) {                                        // annotated fields present, generate the toString() method                    System.out.println("Modifying " + name);                    ClassWriter writer = new ClassWriter(false);                    ToStringGenerator gen = new ToStringGenerator(writer,                            name.replace(‘.‘, ‘/‘), fields);                    creader.accept(gen, false);                    bytes = writer.toByteArray();                }                                // return the (possibly modified) class                return defineClass(bytes, 0, bytes.length);                            } catch (IOException e) {                throw new ClassNotFoundException("Error reading class " + name);            }        }    }    public static void main(String[] args) {        if (args.length >= 1) {            try {                                // get paths to be used for loading                ClassLoader base = ClassLoader.getSystemClassLoader();                URL[] urls;                if (base instanceof URLClassLoader) {                    urls = ((URLClassLoader)base).getURLs();                } else {                    urls = new URL[] { new File(".").toURI().toURL() };                }                                // load the target class using custom class loader                ToStringLoader loader =                    new ToStringLoader(urls, base.getParent());                Class clas = loader.loadClass(args[0]);                                    // invoke the "main" method of the application class                Class[] ptypes = new Class[] { args.getClass() };                Method main = clas.getDeclaredMethod("main", ptypes);                String[] pargs = new String[args.length-1];                System.arraycopy(args, 1, pargs, 0, pargs.length);                Thread.currentThread().setContextClassLoader(loader);                main.invoke(null, new Object[] { pargs });                            } catch (Exception e) {                e.printStackTrace();            }                    } else {            System.out.println("Usage: com.sosnoski.asm.ToStringLoader " +                "report-class main-class args...");        }    }}

為了使用清單 4 代碼,我仍然需要使用 JDK 5.0 編譯與注釋相關(guān)的代碼,然后在產(chǎn)生的類(lèi)集合上運行 Retroweaver。我也需要在類(lèi)路徑中包含 retroweaver.jar 運行時(shí)代碼(因為 Retroweaver 對已轉換的注釋使用它自己的類(lèi))。

清單 5. JDK 1.4 上的 ToString 注釋
[dennis@notebook code]$ java -cp classes:retro/release/retroweaver-rt.jar:lib/  asm-2.0.RC1.jar:lib/asm-commons-2.0.RC1.jar  com.sosnoski.asm.ToStringLoader com.sosnoski.dwct.RunProcessing class com.sosnoski.dwct.RunProcessing class com.sosnoski.dwct.NameModifying com.sosnoski.dwct.NameProcessing class com.sosnoski.dwct.AddressModifying com.sosnoski.dwct.AddressProcessing class com.sosnoski.dwct.CustomerModifying com.sosnoski.dwct.CustomerCustomer: #=12345 Name: Dennis Michael Sosnoski Address: street=1234 5th St. city=Redmond state=WA zip=98052 homePhone=425 555-1212 dayPhone=425 555-1213

清單 5 顯示了生成的 toString() 方法的輸出. 用于 JDK 1.4 的自定義類(lèi)加載器方法不提供 JDK 5.0 instrumentation API 的完全靈活性,但是它適用于所有最近的 JVM,并允許您修改任何應用程序類(lèi)。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
J2EE,J2SE,J2ME,JDK,SDK,JRE,JVM區別
Java開(kāi)發(fā)技術(shù)十年的回顧與展望 , j2,jdk,se,sun,api,版本,技術(shù),su...
JAVA學(xué)習筆記二
J2SE J2EE J2ME JDK JSDK JRE JVM什么意思
jvm 種類(lèi)
在Fedora Linux上安裝JDK6/Java SE 6
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

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