1. 程式人生 > >編譯32位windows系統下可用的JVMTI動態連結庫

編譯32位windows系統下可用的JVMTI動態連結庫

        這3天研究如何編譯32位windows系統下可用的jVMTI動態連結庫。中間過程很多時間都在搭建各種環境,其他時間在學習編譯和各個系統的相關知識,總的來說,受益匪淺。記錄一下3天踩過的坑和解決方法。

        JVM TI是JDK提供的一套用於開發JVM監控, 問題定位與效能調優工具的通用程式設計介面(API)。通過JVMTI,我們可以開發各式各樣的JVMTI Agent。這個Agent的表現形式是一個以c/c++語言編寫的動態共享庫。

        JVMTI Agent原理: java啟動或執行時,動態載入一個外部基於JVM TI編寫的dynamic module到Java程序內,然後觸發JVM源生執行緒Attach Listener來執行這個dynamic module的回撥函式。在函式體內,你可以獲取各種各樣的VM級資訊,註冊感興趣的VM事件,甚至控制VM的行為。

        我們要做的就是編譯這個c/c++編寫的動態共享庫。

  linux windows mac
目標檔案 .o .obj .o
靜態共享庫 .a .lib .a
動態共享庫 .so .dll .dylib

參考gcc編譯引數學習gcc編譯過程

一個C/C++檔案要經過預處理(preprocessing)、編譯(compilation)、彙編(assembly)、和連線(linking)才能變成可執行檔案。

一.環境搭建

      1.本地demo

          該demo是通過attach api,這是一套純java的api,它負責動態地將dynamic module attach到指定程序id的java程序內並觸發回撥。開發一個JVMTI agent。     

 通過git clone程式碼後,開啟專案,下載maven包。使用自帶gcc編譯包後,放到resource資料夾下,修改引數loadAgentPath路徑為自己新編譯的動態連結庫,便可以跑通本地demo.

      2.windows7 32bit

          因為目標是編譯在win7 32位機器上執行的動態連結庫,所以需要安裝一個32位的win7虛擬機器,我用的是vmware,這裡要注意你的mac版本和vmware的版本是否匹配。同時安裝win7映象的時候不要安裝ghost映象。和本地demo一樣,將編譯好的dll檔案放在resource下,修改引數loadAgentPath路徑為自己新編譯的動態連結庫。

      3.ubunto16.04

          需要一個linux環境進行交叉編譯,我選擇了ubunto,教程自行百度。

 

二.工具使用

       1.vmware  vmtools

          mac上一款優秀的虛擬機器軟體,vmtools是用來在本機和虛擬機器進行檔案拷貝和解決全屏等問題的外掛。

       2.MinGW

          交叉編譯工具,安裝在ubunto下,安裝成功後可以自行選擇32還是64位進行編譯。

          生成ForceFGC.o檔案

          i586-mingw32-gcc -c -DBUILD_DLL ForceGC.c

          生成ForceGC.dll檔案

          i586-mingw32-gcc -shared -o ForceGC.dll ForceGC.o -Wl,--kill-at,--out-implib,libForceGC.a

       3.自帶gcc

           可以進行linux下的動態庫編譯

   生成ForceGC.o檔案

  gcc -shared -fPIC -c ForceGC.c -I /usr/lib/jvm/jdk1.8.0_171/include/ -I /usr/lib/jvm/jdk1.8.0_171/include/linux 

   生成ForceGC.so檔案

  gcc -shared -fPIC -o ForceGC.so ForceGC.o

  4.arm-linux-gcc

             可以進行不同cpu架構下的交叉編譯,使用Linux主機編寫的,然後編譯後要在ARM上執行的可執行檔案。多用在嵌入式機器上。

 

三.遇到的問題

        1.windows的命名

             碰到一個很坑的問題,在此記錄一下。因為在windows中報了一個錯有可能是檔案沒有找到造成的,所以我自己做了個實驗。建了一個1.txt的txt檔案,然後讀取他,卻一直報這個檔案系統找不到,一開始以為是虛擬機器的儲存系統造成的問題,後來把這個檔案的路徑打出來也沒問題,最後打出整個的全稱發現,這個檔名是1.txt.txt。然而報錯並不是沒有找到系統檔案。gettempdir()誤導了我。。真正的原因是下面一條。

  2.生成環境下的com.sun.tools不會自己引入,且windows版本的包和linux版本的包不一樣

           一個開始報錯attach的classnotfound。在windows環境下,tools包不會自己引入,和在mac不一樣,需要自己手動引入,我後來把mac上的tools下載了一份拷貝過去手動連結,報了另一個醋,就是java.lang.UnsatisfiedLinkError: sun.tools.attach.BsdVirtualMachine.getTempDir()Ljava/lang/String;我以為是系統檔案沒有找到的錯。然而是因為windows下的tools包和linux下的包不一樣,我又下了windows的包,重新引入錯誤解決。這裡加上system最好。

<groupId>com.sun</groupId>

<artifactId>tools</artifactId>

<version>1.6.0</version>

<scope>system</scope>

<systemPath>D:/Java/jdk1.6.0_27/lib/tools.jar</systemPath>

</dependency>

        3.虛擬機器vm顯示打不開 /dev/vmmon:無此檔案或目錄

可以按下列步驟解決:

1. 退出VMware fusion;

2. 開啟終端;

3. 執行命令:sudo rm -rf /System/Library/Extensions/vmmon.kext ,根據提示輸入管理員密碼;

4. 執行命令:sudo cp -pR /Applications/VMware\ Fusion.app/Contents/Library/kexts/vmmon.kext /System/Library/Extensions/

5. 執行命令:sudo kextutil /System/Library/Extensions/vmmon.kext

6. Quit Terminal 如果出現執行第五步報錯,可以嘗試先執行下面的命令: sudo kextunload /System/Library/Extensions/vmmon.kext 如果不出現Failed to unload com.vmware.kext.vmx86 - (libkern/kext) kext (kmod) start/stop routine failed,恭喜你可以執行第五步命令了,如果出現了,可以先嚐試重啟機器後再執行上述步驟。

 

        4.ubunto下的apt-get MinGW安裝問題

                軟體包找不到的問題,換源,在下載。前面如果不行則手動加入源

        5.arm-linux-gcc的包 

                找了半天都沒找到可以免費下載的包,就不浪費這個時間了,上淘寶花了2塊下載的包。雖然這次最終沒有用到,但還是比較好用的包。安裝使用教程度娘。

        6.vmtools安裝問題

無法 mkdir: 只讀檔案系統”解決辦法