自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

探秘Java 7:JVM動態(tài)語言支持詳解

原創(chuàng)
開發(fā) 后端
Java 7中最引人注目的新功能之一就是對動態(tài)語言的支持。JVM的動態(tài)語言支持基于JSR 292,這一支持的關(guān)鍵在于增加了新的 Java 字節(jié)碼,invokedynamic。本文詳細(xì)介紹了動態(tài)語言支持的情況。

51CTO推薦專題:Java 7,下一代Java開發(fā)平臺詳解

【51CTO精選譯文】JDK 7 增加了對 JSR 292 的支持,在 JVM 中動態(tài)類型語言的運行速度將變得更快。這一支持的關(guān)鍵在于增加了新的 Java 字節(jié)碼,invokedynamic,它用于方法調(diào)用,還有新的連接機(jī)制,其中包含了一個新的構(gòu)造:方法句柄(method handle)。此次JDK 7在動態(tài)語言支持上的更新是Java平臺發(fā)展的重要趨勢之一,在今年6月的JavaOne大會上,這些基于Java平臺的動態(tài)語言也十分的活躍。詳情可參考51CTO之前對JavaOne 2009的報導(dǎo)。

動態(tài)類型語言和 JVM

JVM 可以執(zhí)行 Java 程序,將其編譯機(jī)器獨立的字節(jié)碼。事實上,任何可以使用有效 class 文件表述的功能性語言,都可以運行在 JVM 上。

多年來,運作在 JVM 上語言一直在增加,從 Armed Bear for Common Lisp 到Y(jié)oix。動態(tài)語言的 JVM 實現(xiàn)也越來越多,比如 JRuby 和 Jython,以及 Groovy 腳本語言。

動態(tài)語言的靈活性,尤其是腳本語言,對于實驗性、原型應(yīng)用程序以及需頻繁更新的程序,都具有獨特的吸引力。這種靈活性源自動態(tài)類型。動態(tài)類型語言中運行時(runtime)驗證程序中的值是否與預(yù)期類型一致,相對的,靜態(tài)類型語言,如 Java,是在編譯期間檢查變量類型,而不是值類型。值得一提的是,Java 平臺上另一個前景很被看好的靜態(tài)語言就是Scala:包括Java之父和Groovy創(chuàng)始人在內(nèi)的很多開發(fā)者都很看好Scala這個強(qiáng)類型的、可擴(kuò)展性良好的靜態(tài)語言。

通常,動態(tài)類型比靜態(tài)類型更具靈活性,因為前者允許程序根據(jù)運行時的數(shù)據(jù)生成類型。不過靜態(tài)類型語言的執(zhí)行更為高效,因為它能夠在編譯期間排除錯誤。

動態(tài)類型固有的靈活性與 JVM 的執(zhí)行效率,合二為一。很明顯,這就是它能夠吸引動態(tài)編程語言創(chuàng)建者以及使用這些語言構(gòu)建應(yīng)用程序的開發(fā)者的原因。

JSR 223  動態(tài)語言支持的***步

JSR 223: Scripting for the Java Platform 是將動態(tài)語言引入 JVM 的***步,它是一個規(guī)范,定義了從動態(tài)腳本語言代碼訪問 Java 代碼的 API 接口。它還指定了一個 framework 框架,用戶在 Java 應(yīng)用程序中運行腳本引擎。該規(guī)范及其實現(xiàn)使得包含 Java 和腳本代碼的應(yīng)用程序的創(chuàng)建更為容易。

動態(tài)類型語言的問題

為運行在 JVM 上的動態(tài)類型語言開發(fā)引擎,必須滿足 JVM 所執(zhí)行的 Java 字節(jié)碼的要求,而字節(jié)碼專為靜態(tài)類型語言設(shè)計。對于引擎開發(fā)者,當(dāng)生成字節(jié)碼用于方法調(diào)用,這種設(shè)計一直都是棘手的難點。

方法調(diào)用的字節(jié)碼要求

靜態(tài)類型語言中編譯時進(jìn)行類型檢查,意味著方法調(diào)用,以及它生成的字節(jié)碼,需要知道該方法返回的值類型,以及調(diào)用中指定的參數(shù)類型。

下面為一段 Java 代碼:

  1. String s = "Hello World";   
  2. System.out.println(s); 

這里參數(shù)類型是已知的。System.out.println()并不返回值,如果方法返回值,需要指定返回值的類型。

以上代碼相應(yīng)的字節(jié)碼如下:

  1. ldc #2   
  2. astore_1   
  3. getstatic #3   
  4. aload_1 invokevirtual #4 // Method java/io/PrintStream.println:(I)V 

JVM 中字節(jié)碼的執(zhí)行通常包含對操作對象棧(operand stack)中值的操作。操作棧是一個相當(dāng)于硬件寄存器的虛擬機(jī)。通常,字節(jié)碼會指示 JVM 局部值壓入操作對象棧,將值從棧中取出放進(jìn)局部變量中,復(fù)制或交換棧中的值,或者執(zhí)行生成或使用值的操作。

請看 invokevirtual 一行,它調(diào)用了一個方法,而不是對操作對象棧進(jìn)行操作。從該行注釋,我們可以看到,它指出了以下信息:

◆提供方法的接收器(receiver)類:java.io.PrintStream
◆方法名稱:println
◆方法參數(shù)類型:(I) 表示 Integer
◆方法返回值: V 表示 void

這些信息相當(dāng)于方法的簽名。JVM 查找具有該簽名的方法,在這里,就是 java.io.PrintStream 類中的 println:(I)V。如果該方法不在那個類中,JVM 將在類的子類中繼續(xù)查找。

滿足要求所進(jìn)行的拙劣嘗試

為了讓動態(tài)類型語言滿足字節(jié)碼對方法調(diào)用的要求,已經(jīng)有了多種嘗試,但沒有一種是理想的。

以下面的代碼為例:

  1. function max (x,y) {  
  2.   if x.lessThan(y) then y else x   
  3.  } 

接收器和參數(shù)都沒有指定類型,而對于動態(tài)類型語言,直到運行時才提供類型信息,因此,以上代碼未能滿足方法調(diào)用需提前獲悉類型的要求,也就不能在 Java 平臺上成功地編譯為字節(jié)碼。

問題的解決方法之一是為返回值和方法參數(shù)創(chuàng)建虛假的(synthetic)Java 類型。在這里,虛假表示非真實存在。例如,動態(tài)類型語言在實現(xiàn)是可能將代碼更改為:

  1. Interface50 function max (Interface 51 x,Interface52 y) {  
  2.  if x.lessThan(y) then y else x   
  3.  } 

類型 Interface 51 和 Interface52 并不存在,只是為了滿足相應(yīng)的要求而指定。

另一種方法成為映射調(diào)用(relfected invocation),使用 java.lang.reflect.Method 對象調(diào)用方法,而避開直接調(diào)用方法。這樣也就繞開了指定類型的要求。

第三種方法是為動態(tài)語言的實現(xiàn)創(chuàng)建一個獨特的方法調(diào)用解釋器(interpreter),以運行在 JVM 上。

虛假類型滿足了 Java 字節(jié)碼的要求。但這種方法不但繁復(fù)而且會帶來問題。如果動態(tài)語言引擎需要更改,相應(yīng)的實現(xiàn)器(implementer)必須重新創(chuàng)建虛假 Java 類型,這種操作常會出錯。

運行調(diào)用也有其自身的局限。例如,java.lang.reflect.Method 對象提供了動態(tài)語言所需的方法訪問,但對象必須是運行時可用的特定 Java 類型。雖然,動態(tài)語言可以在運行期間提供類型信息,但不是都可以通過用戶映射的規(guī)范 Java 類型。

JSR 292 —— 動態(tài)語言支持的下一步

JSR 292 為 JVM 引入了一個新的 Java 字節(jié)碼指令,invokedynamic,以及一個新的方法連接機(jī)制。

方法調(diào)用的字節(jié)碼指令

Java 虛擬機(jī)規(guī)范指定了 4 個字節(jié)碼,用于方法調(diào)用:

◆invokevirtual
◆invokeinterface
◆invokestatic
◆invokespecial

新的 invokedynamic 指令

新的 invokedynamic 字節(jié)碼指令的語法與 invokeinterface 指令類似:

  1. invokedynamic < method-specification> < n> 

但,它的 < method-specification> 只需指定方法名稱,對描述符的***要求是它應(yīng)引用非空對象。

invokeinterface 字節(jié)碼指令差不多是這樣的:

  1. invokedynamic #10
  2. //DynamicMethod java/lang/Object.lessThan:(Ljava/lang/Object;) 

重要的是,invokedynamic 字節(jié)碼指令運行動態(tài)語言的實現(xiàn)器(implementer)將方法調(diào)用編譯為字節(jié)碼,而不必指定目標(biāo)的類型,該目標(biāo)包含了方法、調(diào)用的返回類型或方法參數(shù)類型。這些類型對于執(zhí)行指令的 JVM 不必是已知的。但如果未提供接收器的類型,JVM 如何找到該方法?畢竟,JVM 需要連接并調(diào)用真實類型上的真實方法。答案在于,JSR 292 還包含了一個新的動態(tài)類型語言的連接機(jī)制。JVM 使用新的連接機(jī)制獲取所需的方法。

新的動態(tài)連接機(jī)制:方法句柄(method handle)

JDK 7 包含了新包,java.dyn,其中包含了與在 Java 平臺中動態(tài)語言支持相關(guān)的類。其中一個類為 MethodHandle。方法句柄是類型 java.dyn.MethodHandle 的一個簡單對象,該對象包含一個 JVM 方法的匿名引用。

新連接機(jī)制還包含一個引導(dǎo)方法(bootstrap 方法),它是一個方法句柄,決定了調(diào)用現(xiàn)場(call site)調(diào)用的目標(biāo)方法。調(diào)用現(xiàn)場是調(diào)用指令的實例,在本節(jié)中,它就是 invokedynamic 字節(jié)碼指令的實例。包含 invokedynamic 指令的每個類都必須指定引導(dǎo)方法。

JVM ***次遇到具有接收器和參數(shù)的 invokedynamic 字節(jié)碼時,它調(diào)用引導(dǎo)方法。調(diào)用語言支持的方法,可以使用術(shù)語 up-call 來描述。

引導(dǎo)方法反過來選擇相應(yīng)的目標(biāo)方法句柄。然后 JVM 將該方法句柄引用的方法與 invokedynamic 字節(jié)碼關(guān)聯(lián)起來。JVM 下次遇到具有相同接收器和參數(shù)的 invokedynamic 字節(jié)碼時,它將立即調(diào)用之前所選的方法。

方法句柄相當(dāng)簡單,僅包含一個描述特定類型的類型令牌(type toke)。此外,方法句柄隱式地包含一個與其關(guān)聯(lián)的 invoke 方法。要調(diào)用方法句柄,你需要調(diào)用它的 invoke 方法,與調(diào)用對象方法類似,即 MethodHandle.invoke(...)。由于每個方法句柄都具有其自身的類型,因此,它只接受那個類型的 invoke 調(diào)用。如果調(diào)用的類型與方法句柄的類型不匹配,方法句柄將返回異常。

方法句柄 

總之,方法句柄提供了一種連接機(jī)制,它能夠讓 JVM 根據(jù) invokedynamic 字節(jié)碼指令調(diào)用正確的方法。但 JVM 遇到 invokedynamic 字節(jié)碼時,它將使用方法句柄獲得所需的方法。請注意,相對于映射調(diào)用,方法句柄提供了一種更好的方式,來滿足方法調(diào)用的字節(jié)碼要求。相較而言,方法句柄提供了一種命名和連接方法的方式,而無需考慮方法類型或位置,而且這種方式具有完善的類型安全和本地的執(zhí)行速度。

通過接口注入(interface injection)在運行時修改類

接口注入能夠在運行時修改類,這樣類就可以構(gòu)建新的接口。對于動態(tài)類型語言,尤其是基本語言,這是一個常見的功能。但它不屬于 JVM 標(biāo)準(zhǔn)的一部分。該功能還處于調(diào)研階段,以便加入 JSR 292 中。

在 JVM 中支持接口注入,運行時語言將可以推薦新的功能,以模塊化的方式供其自身使用。例如,假設(shè) JVM 在運行的語言的類或類集合需要串行化的類型,而它尚未在該語言實現(xiàn)。運行時該語言可以定義一個串行定義為可注入的接口。它還可以定義一個注入方法。該方法定義該語言將為哪個類指定新的串行能力。對相關(guān)對象調(diào)用該注入方法,就可以完成注入。利用接口注入,可以使 JVM 中的動態(tài)類型語言很方便地與 JVM 中其他語言進(jìn)行整合。

總結(jié)

多年來,在 JVM 上運行的語言越來越多。在 JVM 中支持動態(tài)類型語言,對于使用動態(tài)語言的開發(fā)者非常具有吸引力。因為,動態(tài)類型讓開發(fā)者更具靈活性,而且 JVM 具有更好的執(zhí)行效率。但是,對于動態(tài)類型語言,滿足方法調(diào)用的字節(jié)碼的要求非常困難。為了應(yīng)對這一難題,JSR 292 提供了新的字節(jié)碼 invokedynamic 以及新的基于方法句柄的連接機(jī)制。此外,目前還在進(jìn)行調(diào)研在 JSR 292 中引入接口注入,它能夠在運行修改類,從而可以實現(xiàn)新的接口。

原文:New JDK 7 Feature: Support for Dynamically Typed Languages in the Java Virtual Machine

作者:Ed Ort

【編輯推薦】

  1. JavaOne揭示Java領(lǐng)域的幾大趨勢 向多語言發(fā)展
  2. Java語言將淡出 JVM寶座爭奪戰(zhàn)預(yù)熱
  3. 7月編程語言排行榜:Java,正在老去的王者
  4. JVM的動態(tài)語言支持:為新一代流行語言鋪平道路
  5. 基于JVM的語言正在開始流行
責(zé)任編輯:yangsai 來源: 51CTO.com
相關(guān)推薦

2009-06-15 16:21:05

Java虛擬機(jī)動態(tài)語言支持

2009-06-10 16:09:56

netbeans ru動態(tài)語言

2010-06-22 11:07:42

JDK 7Java開發(fā)Java

2009-03-04 10:11:58

StringsjavaSun

2010-07-30 09:09:07

JVM動態(tài)語言Groovy

2024-07-26 10:23:52

2009-12-23 09:23:17

Groovy 1.7

2009-12-24 09:19:48

JVMJRubyEngineYard

2009-08-24 08:37:52

Windows 7防火墻

2021-02-22 21:49:33

Vue動態(tài)組件

2010-03-01 18:26:25

Python

2020-05-08 16:55:48

Java虛擬機(jī)JVM

2009-06-14 21:54:37

動態(tài)語言Java腳本API

2011-07-29 09:31:32

JDK 7

2010-12-01 15:28:19

ProbeVueJava

2009-03-08 19:10:57

Windows 7多語言

2010-02-03 18:06:42

Python語言

2010-02-22 18:25:07

2009-07-24 09:41:45

Java 7 G1垃圾回收器

2010-07-01 09:29:15

Java腳本語言javax.scrip
點贊
收藏

51CTO技術(shù)棧公眾號