kvm文档翻译-第六章
說明
翻譯KVM的文檔,只是為了個人學習以做記錄.如果有翻譯不周到的地方,請指出,我會修正的.
為何翻譯該文檔
此KVM不是目前特別火的Kernel-based Virtual Machine(一個開源的系統虛擬化模塊).而是一個JAVA 的虛擬機.是J2ME cldc 的一個實現.其源碼的難度比hotspot簡單多了.因此,想通過研讀KVM,以加深對hotspot的理解
編譯選項,宏
本節列出了vmcomon/h/main.h中定義的各種C預處理器標志、定義和宏。了解這些標志的含義有助于移植工作,因此請閱讀下面的文檔和vmcomon/h/main.h文件。
注意 – 不要更改vmcomon/h/main.h中提供的值,這些值最好在端口特定的machine_md.h文件中被重寫。
另外請注意,在我們的引用實現中,這些標志中的許多通常都是從makefiles中重寫的。
對于每個定義,我們給出一個簡短的摘要及其默認定義。這些標志和宏也記錄在vmcomon/h/main.h中。
普通的編譯選項
以下定義控制在開始移植工作之前必須設置的與平臺相關的常規編譯器選項。不正確的設置通常會導致虛擬機故障。
#define COMPILER_SUPPORTS_LONG 1
如果編譯器支持長(64位)整數,則啟用此標志。
#define NEED_LONG_ALIGNMENT 0
指示KVM,主機操作系統和編譯器的64位整數都需要8字節對齊。
#define NEED_DOUBLE_ALIGNMENT 0
指示KVM,主機操作系統和編譯器,是否需要double8字節對齊。(只有在啟用了浮點數支持時,此標志才有意義)
額外提示. 為了生成更好的代碼,最好指定字節序.應該在平臺相關的頭文件中,將下面的其中一個設為1.
#define BIG_ENDIAN 0
#define LITTLE_ENDIAN 0
如果您將COMPILER_SUPPORTS_LONG 置為零,則無需將這些“endian”變量之一設置為“1”。(詳見第9章。)
還要注意,如果編譯器支持64位整數算術,并且已經設置了標志
#define COMPILER_SUPPORTS_LONG
您應該為long64和ulong64類型提供定義。如果編譯器不支持64位整數(或者由于其他原因將標志設置為0),則會自動為您創建這兩種類型的結構定義。(見第9章。)
系統配置選項
以下定義允許您控制要包含在平臺中的組件和功能
#define IMPLEMENTS_FLOAT 1
打開或關閉kvm中的浮點支持。在那些符合CLDC規范版本1.1的實現中應為“1”,在那些符合CLDC規范版本1.0的實現中應為“0”。
#define PATH_SEPARATOR ‘:’
路徑中使用的路徑分隔符。只有在為基于命令行的系統使用默認類加載器時,此定義才有意義。(在vmcomon/h/loader.h中定義)
#define ROMIZING 1
打開或關閉類預鏈接/預加載(JavaDecompact)支持。如果啟用此選項,KVM將直接在虛擬機中預鏈接所有系統類,從而大大加快應用程序的啟動速度。詳見第14章。
#define USE_JAM 0
在KVM內部是否啟用 Java應用程序管理器(JAM)。
#define ASYNCHRONOUS_NATIVE_FUNCTIONS 0
指示KVM使用可選的異步本地函數。有關詳細信息,請參閱第11.4節“異步本地方法”和第12章。
#define USE_KNI 1
這個選項是在kvm 1.0.4中引入的。啟用后,系統將包含k本地接口(kni)所需的一些代碼。如果你不打算使用Kni(你應該!),我們建議您關閉此選項,因為在關閉此選項的情況下,舊樣式的本地函數將運行得稍快。有關kni的更多信息,請參閱kni規范。
Palm 平臺特定的選項
以下定義允許您控制特定于Palm的系統配置選項。所有這些功能最初都是為PalmOS版本的KVM設計的,但它們也可能對其他平臺有用。
注意 – Palm OS的CLDC實現不再可用。
#define USESTATIC 0
指示KVM使用特定于Palm的優化,其中某些不可變的運行時數據結構從“動態RAM”移動到“存儲RAM”,以節省Java堆空間。此機制的假實現也可用于Windows和Solaris版本的KVM(用于調試)。
#define CHUNKY_HEAP 0
指示KVM使用一個優化,允許KVM在多個塊或段中分配Java堆。這使得虛擬機可以在某些平臺(如Palm OS)上分配更多堆空間。
#define RELOCATABLE_ROM 0
指示KVM使用優化,其中使用可重定位(可移動)表示來存儲預鏈接的系統類。這允許將romized(javadecompacted)系統類存儲在Palm OS等設備中。
Memory allocation settings
以下定義影響KVM分配的內存大小。
#define DEFAULTHEAPSIZE 256*1024
KVM在虛擬機啟動時分配的Java堆大小。此值通常從makefiles中重寫。請注意,從kvm 1.0.3開始,可以重寫命令行中的堆大小值(在支持命令行操作的端口中)。堆大小值必須是可除以4的數字。數字必須在16K到64M之間。
#define INLINECACHESIZE 128
如果啟用了EnableFastBytecodes選項,則在虛擬機啟動時kvm保留的特殊內聯緩存區域的大小。內聯緩存機制通過使用Deutsch&Schiffman在20世紀80年代早期推廣的技術來加速kvm中的方法查找。此處的大小表示為許多內聯緩存項(每個項需要12-16字節,具體取決于目標平臺)。
#define STACKCHUNKSIZE 128
KVM內的Java線程的執行堆棧在必要時自動增長和收縮。此值定義需要分配新堆棧塊時新堆棧幀塊的默認大小。減少默認堆棧塊大小將使新Java線程的創建成本較低,但在運行需要大量堆棧空間的程序(即,具有大量嵌套方法調用的程序)時,將降低VM的執行速度
#define STRINGBUFFERSIZE 512
虛擬機在各種字符串操作中內部使用的靜態分配區域的大小(字節)。
注意 – 作為一般原則,KVM在虛擬機啟動時分配所需的所有內存。在運行時,所有內存都分配在預先分配的區域內。當然,如果虛擬機調用在Java堆外部執行動態內存分配的宿主系統特有的本地函數(如圖形函數),情況可能會發生變化。
GC 選項
以下選項啟用壓縮垃圾收集。請注意,當前壓縮不能在具有分段(非連續)內存體系結構的平臺上使用。
#define ENABLE_HEAP_COMPACTION 1
如果將以下選項設置為非零值,則會導致每次分配都發生垃圾收集。這樣更容易發現垃圾收集問題。由于此選項使虛擬機運行非常緩慢,因此應在生產版本中關閉此選項。
#define EXCESSIVE_GARBAGE_COLLECTION 0
類加載選項
一些KVM平臺可能希望禁止將任何新類加載到任何系統包中。下面的宏定義包名稱是否是這些受限制的包之一。默認情況下,該系統防止動態類加載到java.*和Javax.*
#define IS_RESTRICTED_PACKAGE_NAME(name) \ ((strncmp(name, "java/", 5) == 0) || \ (strncmp(name, "javax/", 6) == 0))解釋器執行選項 (since KVM 1.0)
以下宏允許您打開和關閉控制解釋器執行的某些功能。生產版本的默認值如下所示。
#define ENABLEFASTBYTECODES 1
打開或關閉運行時字節碼替換和方法內聯緩存。此選項將虛擬機的性能提高約10-20%,但會將虛擬機的大小增加幾千字節。請注意,字節碼替換不能在字節碼存儲在非易失性內存(如ROM)中目標平臺上執行
#define VERIFYCONSTANTPOOLINTEGRITY 1
指示虛擬機在運行時執行常量池查找時驗證常量池項的類型。稍微降低運行時性能,但出于安全和安全原因,通常建議保持運行時性能。
其他定義和解釋器宏:
#define BASETIMESLICE
此變量的值確定虛擬機執行線程切換、事件通知和其他定期需要的操作的基本頻率(作為執行的字節碼數)。較小的數目可以減少事件處理和線程切換延遲,但會導致解釋器運行更慢。
#define DOUBLE_REMAINDER(x, y) fmod(x,y)
在interpret中定義的一種編譯宏,用于查找兩個浮點數的模。
#define SLEEP_UNTIL(wakeupTime)
此宏使虛擬機休眠,直到當前時間(由函數currentTime_md()的返回值指示)大于或等于喚醒時間。sleep_until的默認實現是一個繁忙的循環。出于節約電池的原因,大多數平臺通常都應該提供更有效的實現。更多詳情請參閱第12.4節“電池節電”。
解釋器執行技術(在kvm 1.0.2之后)
自1.0.2版發布以來,kvm的解釋器設計比kvm 1.0高出15-30%的性能,并且沒有失去任何的ansi c c可移植性。實際的性能改進百分比取決于目標平臺和用于編譯KVM的C編譯器的功能。性能改進是以下四種技術相互獨立使用的結果:
- 重新構造解釋器代碼,以便在解釋器運行時將虛擬機寄存器放入本地C變量中。
- 將不常用的Java字節碼拆分為單獨的解釋器循環子程序。這使得C編譯器可以更好地優化代碼以獲得更頻繁使用的字節碼。
- 將Java線程重新調度的測試從解釋器循環的頂部移動到分支字節碼。這減少了用于控制線程切換的時間片計數器的開銷。
- 填充字節碼空間,以便C編譯器為解釋器的主switch語句生成更好的代碼。
這些技術不依賴于任何特定于編譯器的特性,因此可以跨各種C編譯器進行移植。下面將詳細討論每種技術和相應的宏。
將虛擬機寄存器復制到局部變量
在執行字節碼時,經常訪問kvm的虛擬機寄存器(ip、sp、lp、fp、cp)。在kvm 1.0中,所有這些虛擬機寄存器都定義為全局C變量。從kvm 1.0.2開始,這些寄存器仍然主要定義為全局變量,但是如果LOCALVMREGISTERS選項為on,則在解釋器執行時,它們將被復制到本地變量。然后,一個好的C編譯器將優化解釋器循環,以便將這些局部變量放入機器寄存器中,從而大大加快執行速度
#define LOCALVMREGISTERS 1
打開或關閉虛擬機寄存器的本地化
#define IPISLOCAL 1
#define SPISLOCAL 1
#define LPISLOCAL 0
#define FPISLOCAL 0
#define CPISLOCAL 0
這些宏允許您具體控制解釋器循環應在本地使用哪些虛擬機寄存器。添加這些宏是為了更好地控制寄存器分配,因為許多受資源約束的平臺可能沒有許多可用的物理硬件寄存器。
為特定平臺優化選擇這些選項需要仔細檢查編譯器生成的機器代碼,并進行大量實驗。默認情況下,IP(指令指針)和SP(堆棧指針)在本地分配,而LP(本地指針)、FP(幀指針)和CP(常量池指針)保留在全局變量中。
注意 – 如果您使用LOCALVMREGISTERS選項,并且希望對實現Java字節碼的代碼做進一步的更改,記住的最重要的一點是確保虛擬機寄存器的本地副本在調用期望它們的虛擬機中的函數之前被復制回它們的全局變量。在它們的全局變量中。如果不這樣做,將導致隱藏的錯誤。虛擬機寄存器可以使用宏vmsave保存到全局變量中。使用宏vmrestore將它們還原回其局部變量。例如,返回的字節碼可能需要調用monitorexit(),為此,必須按如下方式進行調用:
VMSAVE result = monitorExit(...); VMRESTORE將不常見的字節碼拆分為單獨的子例程
KVM 1解釋器在單個大switch語句中擁有所有Java字節碼的代碼。然而,大多數Java字節碼很少執行。如果將使用頻率更高、使用頻率更低的字節碼的代碼放在單獨的例程中,C編譯器通常可以更好地優化結果較小的解釋器循環。這也有助于編譯器在使用LOCALVMREGISTERS選項時更容易找到虛擬機寄存器的硬件寄存器
#define SPLITINFREQUENTBYTECODES 1
打開此選項允許C編譯器為頻繁和不經常使用的字節碼生成單獨的解釋器循環。
請注意,處理字節碼的代碼現在包含在名為bytecodes.c的文件中。所有字節碼的代碼都保存在這里,并通過使用許多內部宏定義(STANDARDBYTECODES, INFREQUENTSTANDARDBYTECODES, FLOATBYTECODES 和 FASTBYTECODES)選擇性地編譯。
bytecodes.c中的代碼是從另一個名為execute.c的新文件執行的。如果啟用了SPLITINFREQUENTBYTECODES選項,則文件bytecodes.c將包含在execute.c中兩次:一次用于名為SlowInterpret()的例程,另一次用于例程Interpret()。上面提到的四個宏用于控制將適當的字節碼擴展到正確的子例程中。
將線程重新調度測試移動到分支點
舊的kvm 1.0解釋器測試了在執行每個字節碼之前是否需要重新調度(切換線程)。通過改變測試的位置,解釋器的性能提高了5%左右,因此測試只在每個分支、goto、call和return指令之后執行。
舊解釋器中的線程調度發生在執行了一定數量的字節碼時。默認情況下,這個數字是線程優先級的100倍。在新的解釋器中,當執行了1000次的分支、調用或返回字節碼時,默認情況下會重新安排線程
#define RESCHEDULEATBRANCH 1
啟用此選項將更改線程切換機制,以便將線程切換測試移動到分支點。請注意,啟用此選項會影響從kvm 1.0繼承的baseTimeslice宏的值。當此選項關閉時,線程調度與kvm 1.0中的一樣運行。
填充字節碼空間
Java虛擬機規范定義了200個標準字節碼,另外還保留了四個其他字節碼供其他用途使用。然而,當字節碼(switch)表的大小正好為256時,許多C編譯器會生成更好的代碼。
#define PADTABLE 0
打開此選項將填充解釋器交換表,使指令數為256。這將增加虛擬機的大小,但允許解釋器在某些平臺上更快地運行
Java-level 調試選項
KVM 1.0.2版本引入了一種新的Java級調試器接口,該接口允許KVM插入第三方Java調試器環境和支持JDWP(Java調試線協議)協議的集成開發環境(IDE)。本節中的宏與Java級調試器選項相關。
注意 – 重要的是要注意,用于Java級調試和VM級調試的調試設備之間存在根本區別。
Java級調試工具與KVM執行的Java程序的調試有關。VM級調試工具用于在本地(C)代碼級別調試KVM本身。
#define ENABLE_JAVA_DEBUGGER 0
包含大量的調試器支持代碼,這些代碼是將KVM插入第三方Java調試器或集成開發環境(如FordE或Borland JBuilder)所必需的。
有關Java級調試器工具和KDWP接口的更多信息在第16章“Java級調試支持(KDWP)”中提供。
VM-level 調試 和 追蹤 選項
KVM提供了大量的調試和跟蹤工具,可用于在本地(C)代碼級別檢查KVM本身的行為。這些設施在移植過程中非常有用。
所有VM級調試和跟蹤選項都應在生產版本中關閉
Includ 和 執行
#define INCLUDEDEBUGCODE 0
包括大量調試和日志記錄代碼,這些代碼在將虛擬機移植到新平臺時非常有用。此選項應在生產版本中關閉。
#define ENABLEPROFILING 0
打開或關閉允許您監視虛擬機執行并獲取執行統計信息的某些分析功能。打開此選項會大大降低虛擬機的執行速度。此選項應在生產版本中關閉。
追蹤選項
在kvm 1.0中,所有跟蹤選項都是編譯標志,只能通過重新編譯虛擬機來更改這些標志。在kvm 1.0.2中,所有這些跟蹤選項都被更改為可從命令行控制的全局變量。這使得打開和關閉單個跟蹤選項更加容易。只有在啟用INCLUDEDEBUGCODE模式編譯虛擬機時,這些全局變量(和命令行開關)才可用。
| -traceallocation | 追蹤內存分配 |
| -tracedebugger | trace the debugging interface (since KVM 1.0.3) |
| -tracegc | 追蹤gc |
| -tracegcverbose | 追蹤gc,更多詳情 |
| -traceclassloading | 追蹤類加載 |
| -traceclassloadingverbose | 追蹤類加載,更多詳情 |
| -traceverifier | 追蹤 class file的驗證 |
| -tracestackmaps | 追蹤 stack maps 的行為 |
| -tracebytecodes | 追蹤 bytecode 的執行 |
| -tracemethods | 追蹤 方法調用 |
| -tracemethodsverbose | 追蹤 方法調用, 更多詳情 |
| -traceframes | 追蹤 stack frames |
| -tracestackchunks | 追蹤stack chunk 的分配 |
| -traceexceptions | 追蹤 異常 處理 |
| -traceevents | 追蹤事件系統的處理 |
| -tracethreading | 追蹤多線程系統的處理 |
| -tracemonitors | 追蹤monitor的行為 |
| -tracenetworking | 追蹤網絡訪問 |
| -traceall | 同時激活上面的所有跟蹤選項 |
如果目標平臺不支持命令行操作,則可以通過在文件vmcomon/src/global.c中更改這些選項的默認值,或通過定義設置和重置這些選項的圖形用戶界面來直接控制這些選項。
此外,您可以通過修改以下選項來控制打印出的跟蹤消息是否簡潔或更詳細
#define TERSE_MESSAGES 0kvm還包含一個堆棧跟蹤打印功能,可以打開它來幫助更詳細地調試異常和錯誤(代價是占用一些額外的內存)。默認情況下,當INCLUDEDEBUGCODE標志打開時,此模式自動打開。
#define PRINT_BACKTRACE 0異常處理宏
注意 – kvm使用的內部錯誤處理宏已在kvm 1.1中重新設計,以支持重新設計的類加載器。
解釋器使用內部錯誤處理宏,如代碼示例1所示。
如果有對宏THROW(error)的調用,在“正常代碼”內的任何地方,VM都會立即跳轉到錯誤處理代碼。此宏的使用可以嵌套,無論是在詞法上還是動態上。throw跳轉到最內部的catch錯誤處理代碼。(各種try、throw和catch宏在vmcomon/h/global.h中定義。)
CODE EXAMPLE 1 Error handling macros TRY { normal code } CATCH (error) { error handling code } END_CATCH always continue here默認情況下,使用setjmp和longjmp模擬此行為。但是,已經提供類似機制的平臺(如palmos)應該使用本地機制。
kvm 1.1也有新的宏來控制虛擬機的關閉。這些宏在代碼示例2中進行了說明。
CODE EXAMPLE 2 VM shutdown macros VM_START { normal VM code } VM_FINISH (value) { code to execute before VM shuts down } VM_END_FINISH與其調用普通的c exit函數,從vm退出的正確方法是調用macro vm_exit(value)。調用此宏將使vm的控件立即傳輸到VM_FINISH(value)宏后面的代碼。傳遞給此代碼的值通常表示關閉時VM將返回的退出代碼。
其他宏和選項
#define UNUSEDPARAMETER(var)
引用實現中的某些函數采用了它們不使用的參數。有些編譯器會發出警告,而有些則不會。對于發出警告的編譯器,它們在如何指示不使用變量是有意的以及不希望收到警告方面有所不同。這個宏應該做任何必要的事情來讓編譯器保持安靜。
重寫makefiles中的編譯標志和其他選項
在使用gnumake構建kvm時,通常使用以下參數。
gnumake ROMIZING=false在禁用romizing的情況下構建kvm。也就是說,不要靜態地將所有系統類鏈接到KVM可執行文件中。(默認設置是在啟用romizing的情況下構建kvm。)
gnumake DEBUG=true使用Java級調試器和VM內部調試代碼構建KVM
gnumake USE_JAM=true使用啟用Java應用程序管理器(JAM)來構建KVM
gnumake GCC=true使用GNU C編譯器而不是標準的Sun編譯器(在Solaris上)
gcc=true是在Linux上開發時的默認選項,這是使用cygwin工具在Windows上編譯的設置。
gnumake USE_KNI=false構建不帶kni功能的kvm。(默認設置是在啟用Kni的情況下構建kvm。)
總結
以上是生活随笔為你收集整理的kvm文档翻译-第六章的全部內容,希望文章能夠幫你解決所遇到的問題。