giovedì 19 agosto 2010

Maxine VM & Eclipse

This post is a brief howto for the installation of the Maxine VM in order to be used from Eclipse. This post is not meant to substitute the official howto, but to add a few details on the installation instructions obtained from my experience in this process.
I personally did the following steps using my Ubuntu Linux 10.4 (kernel 2.6.32-22) x86_64, using Eclipse Helios (3.6), Mercurial 1.4.3, MercurialEclipse 1.6.0, CDT 7.0.0 and the JDK 1.6.0_20 from the Ubuntu repositories. The following is also the solution of my problem thread on the users mailing list.

Downloading the Maxine source tree
Maxine is organized into several projects, and in order to have a complete environment you have to check out all the projects. Being a Sun's project, Maxine exploits Mercurial (hg) to manage the source tree. In order to checkout the source tree you have to build a directory to contain all the tree, for instance maxine-hg (I've this convention of placing the name of SCM in the directory name since I use different SCM for different projects). Enter the above directory and clone the repository:

cd maxine-hg
hg clone https://kenai.com/hg/maxine~maxine maxine
The process will start downloading the source tree, this will take a while depending on the network speed. At the end of the process you will find a maxine directory into the maxine-hg one, inside the former you will find a directory for every project as shown below:


$ ls maxine-hg/maxine
Assembler  bin  C1X  CRI        JDWP       Native  TeleJDWP  VMDI
Base       C0X  CPS  Inspector  MaxineC1X  Tele    VM

Now it's time to compile the maxine vm in order to see if the system is ready to host it. In order to compile you need to set the JUNIT4_CP to the jar of Junit4 and JAVA_HOME to the home of the JDK (that on Ubuntu is /usr/lib/jvm/java-6-sun). So do the following:

export JUNIT4_CP=/sviluppo/java/jars/junit4.4jar
export JAVA_HOME=/usr/lib/jvm/java-6-sun
maxine-hg/maxine/bin/max build

If everything goes well, after a couple of minutes you will have the maxine machine compiled. This means that your system is ready to compile it and you are able to build it also in Eclipse. Do a max clean to clean all the compiled stuff and start Eclipse.


Importing the projects into Eclipse
Once the Maxine source tree is ready, it can be imported into Eclipse. The official Maxine/Eclipse HowTo states that you should do a plain import of the maxine container directory (maxine-hg/maxine in the above). This could generate some problems because such kind of import does a copy of the resource you are importing into the workspace. This means, as emphasized by the official guide, that you are working on an isolated source tree and that, after an update of the source tree itself, you should rei-mport the source tree again. But this could cause other problems: if you don't delete the projects removing their disk content too, your import will be incomplete and you'll be stumbled with strange compilation errors.
My suggestion is therefore to connect Eclipse to the Mercurial source tree:
  • select Import from the File menù;
  • instead of importing an existing Java project, import an existing Mercurial project from a local repository;
  • specify the maxine-hg/maxine directory as the root directory of the project, that is the Mercurial local repository. The dialog will show you all the projects to import, check all of them and if you are working with working sets select a working set to which the projects will be added (in my case Maxine-RVM). Click Finish to complete the import process;
  • when the import finishes, you will see the projects listed in the project explorer, and all the projects will be initially opened. Please note that after a while, depending on your computer speed, all the projects will be decorated with Mercurial informations, like the tip;

  •  now you can compile the projects from within Eclipse, but before that you have to specify the JAVA_HOME variable (or at least check it exists) as you did for the command-line compilation. This variable is needed for compiling the native code (Native project). To set it, open the Window, Preferences menu', go to the C/C++ preference page and select the building variables, then add the variable and point it to the JAVA_HOME you used for the command line compilation. The CDT will use gmake to compile the sources, using the JAVA_HOME variable defined here;

  • now you can start the compiling process, using the Project, Build All or Project, Build Working Set menu items. The compilation should complete without errors (but with around 1000 warnings). I had different compilation problems in the first trial:
    • cannot compile the Native project due to a missing jni.h: this means that the JAVA_HOME variable is pointing to a wrong location or that it is not set at all. Double check it!
    • inexistent imports or wrong access to methods/fiels: this means that your sources are not updated to the last version, or that you have done a wrong import over an existing one. Try removing all the projects from Eclipse (remove them also from the workspace) and re-import them again.
    • errors related to @Override annotations: there is something wrong with the project settings. Check if you enabled to report errors instead of warnings about such annotations.
  • once the compilation has been completed, you can generate the boot image. To do so, run the BootImageGenerator-default from the Run menu;

  • the image generator will start compiling the boot image, and you will see a lot of messages scrolling on the console. The production of the image will took around 2/3 minutes;
  •  you are almost done, before launching the VM or the Inspetor you have to check if the $JAVA_HOME directory includes a jdk directory, if not define a symbolic link to fake on the JDK installation layout:
cd $JAVA_HOME
sudo ln -s `pwd` jdk
  • now you can launch the Inspector using, for example, the MaxineInspector-HelloWorld from the Debug menu;
  •  after a while the Inspector window will appear, and the system will stop at a predefined breackpoint. Click on the Resume button of the Inspector GUI to complete the process. After a few seconds the Inspector menu bar will change color passing from green to red. This means that the thread has completed its execution, and scrolling on the Eclipse console you can see the "Hello World" message.


Problems launching the Inspector
During my tests I was unable to launche the Inpsector, having Eclipse to stop at a breackpoint and resulting in the following stack trace and debug information:


FATAL VM ERROR[1]: error in initializeSystemClass
Faulting thread: main[id=1]
------ Stack dump for thread main[id=1] ------
        -> com.sun.max.vm.runtime.FatalError.dumpStackAndThreadLocals(Lcom/sun/max/unsafe/Pointer;Z)V [0x43be38a0+101]
        -> com.sun.max.vm.runtime.FatalError.unexpected(Ljava/lang/String;ZLjava/lang/Throwable;Lcom/sun/max/unsafe/Pointer;)Lcom/sun/max/vm/runtime/FatalError; [0x43b8fce8+412]
        -> com.sun.max.vm.runtime.FatalError.unexpected(Ljava/lang/String;Ljava/lang/Throwable;)Lcom/sun/max/vm/runtime/FatalError; [0x43be8530+54]
        -> com.sun.max.vm.run.java.JavaRunScheme.initialize(Lcom/sun/max/vm/MaxineVM$Phase;)V [0x43be81a0+117]
        -> com.sun.max.vm.VMConfiguration.initializeSchemes(Lcom/sun/max/vm/MaxineVM$Phase;)V [0x43b92f78+233]
        -> com.sun.max.vm.run.java.JavaRunScheme.initializeBasicFeatures()V [0x43b9cd28+94]
        -> com.sun.max.vm.run.java.JavaRunScheme.run()V [0x43af4ba8+38]
        -> com.sun.max.vm.thread.VmThread.executeRunnable(Lcom/sun/max/vm/thread/VmThread;)V [0x43b936a8+208]
        -> com.sun.max.vm.thread.VmThread.run(Lcom/sun/max/unsafe/Pointer;Lcom/sun/max/unsafe/Pointer;Lcom/sun/max/unsafe/Pointer;)V [0x43af20f8+895]
        -> native{/sviluppo/java/src/maxine-hg/maxine/Native/generated/linux/libjvm.so (0x7fb0ff2e5000) at thread_run (0x7fb0ff2fd10a+390)}
------ Thread locals for thread main[id=1] ------
                              SAFEPOINT_LATCH: {E} 0xb94118  {D} 0xb94238  {T}
             SAFEPOINTS_ENABLED_THREAD_LOCALS: {E} 0xb94118  {D} 0xb94118  {T} 0xb94118
            SAFEPOINTS_DISABLED_THREAD_LOCALS: {E} 0xb94238  {D} 0xb94238  {T} 0xb94238
           SAFEPOINTS_TRIGGERED_THREAD_LOCALS: {E} 0xb93ff8  {D} 0xb93ff8  {T} 0xb93ff8
                         NATIVE_THREAD_LOCALS: {E} 0xb94358  {D} 0xb94358  {T} 0xb94358
                                 FORWARD_LINK: {E} 0  {D} 0  {T} 0
                                BACKWARD_LINK: {E} 0xb97118  {D} 0xb97118  {T} 0xb97118
                       AT_SAFEPOINT_PROCEDURE: {E} 0  {D} 0  {T} 0
                             EXCEPTION_OBJECT: {E} 0  {D} 0  {T} 0
                                           ID: {E} 0x1  {D} 0x1  {T} 0x1
                                    VM_THREAD: {E} 0x40fa4008 main[id=1]  {D} 0x40fa4008 main[id=1]  {T} 0x40fa4008 main[id=1]
                                      JNI_ENV: {E} 0x7fb0ff508540  {D} 0x7fb0ff508540  {T} 0x7fb0ff508540
                       LAST_JAVA_FRAME_ANCHOR: {E} 0x7fb100021e18  {D} 0  {T} 0
                                MUTATOR_STATE: {E} 0x1  {D} 0  {T} 0
                                       FROZEN: {E} 0  {D} 0  {T} 0
                                  TRAP_NUMBER: {E} 0  {D} 0  {T} 0
                     TRAP_INSTRUCTION_POINTER: {E} 0  {D} 0  {T} 0
                           TRAP_FAULT_ADDRESS: {E} 0  {D} 0  {T} 0
                          TRAP_LATCH_REGISTER: {E} 0  {D} 0  {T} 0
                   HIGHEST_STACK_SLOT_ADDRESS: {E} 0x7fb100023000  {D} 0x7fb100023000  {T} 0x7fb100023000
                    LOWEST_STACK_SLOT_ADDRESS: {E} 0x7fb0fffe4000  {D} 0x7fb0fffe4000  {T} 0x7fb0fffe4000
             LOWEST_ACTIVE_STACK_SLOT_ADDRESS: {E} 0  {D} 0  {T} 0
                          STACK_REFERENCE_MAP: {E} 0xb943a8  {D} 0xb943a8  {T} 0xb943a8
                         STACK_REFERENCE_SIZE: {E} 0x1008  {D} 0x1008  {T} 0x1008
                  IMMORTAL_ALLOCATION_ENABLED: {E} 0  {D} 0  {T} 0
                           INTERPRETED_METHOD: {E} 0  {D} 0  {T} 0
                       NATIVE_CALL_STACK_SIZE: {E} 0  {D} 0  {T} 0
                                     TLAB_TOP: {E} 0x7fb0df448000  {D} 0  {T} 0
                                    TLAB_MARK: {E} 0x7fb0df43f8b0  {D} 0  {T} 0
                                 TLAB_TOP_TMP: {E} 0  {D} 0  {T} 0
                                TLAB_MARK_TMP: {E} 0  {D} 0  {T} 0
                                TLAB_DISABLED: {E} 0  {D} 0  {T} 0
                           TLAB_REFILL_POLICY: {E} 0x7fb0df0d8000  {D} 0  {T} 0
                               ERROR_CONTEXTS: {E} 0x42792b10  {D} 0  {T: {E} 0  {D} 0  {T} 0
                       AT_SAFEPOINT_PROCEDURE: {E} 0  {D} 0  {T} 0
                             EXCEPTION_O


As you can see from the debug information, there is a link error because the library for amd64 cannot be found under the jdk directory. This is because the JDK installed by the Ubuntu repositories as a layout that is not the same of the official Java JDK. The solution, as detailed above, is to fake this layout creating a link to the jdk directory.

Nessun commento: