<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>Volker Simonis&apos;s Blog</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/simonis/" />
<modified>2008-01-25T01:11:03Z</modified>
<tagline></tagline>
<id>tag:weblogs.java.net,2008:/blog/simonis/427</id>
<generator url="http://www.movabletype.org/" version="3.01D">Movable Type</generator>
<copyright>Copyright (c) 2008, simonis</copyright>
<entry>
<title>HotSpot development on Linux with NetBeans - Part 2</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html" />
<modified>2008-01-25T01:11:03Z</modified>
<issued>2008-01-25T00:33:59Z</issued>
<id>tag:weblogs.java.net,2008:/blog/simonis/427.9061</id>
<created>2008-01-25T00:33:59Z</created>
<summary type="text/plain">Here comes the second part of &quot;HotSpot development on Linux with
NetBeans&quot;. While the first part focused on building and running
the different flavors (opt/debug, client/server JIT compiler, template/C++
interpreter) of the HotSpot VM on Linux/x86, this second part concludes
with a short evaluation of NetBeans 6.0 as an development environment for
HotSpot hacking.</summary>
<author>
<name>simonis</name>

<email>volker.simonis@gmail.com</email>
</author>
<dc:subject>Community: OpenJDK</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/simonis/">
<![CDATA[<html>

<head>

<style type="text/css" id="internalStyle">
  body {
    font-family: arial, helvetica, sans-serif;
    font-size: 10pt;
  }

  pre.listing {
    display: table;
    color: black;
    background-color: lightgray;
    border-style: solid;
    border-width: 1px;
    border-color: darkgray;
    margin: 8px 0px 5px 0px;
    padding: 2px;
    width: auto; 
    overflow: auto;  
    font-family: monospace;
  }

  .warning {
    color: red;
    font-size:  0.8em;
    text-align: center;
  }

  .mh1 {
    color: #202080;
    font-size:  1.2em;
    font-weight: bold;
  }

  .mh2 {
    color: #202080;
    font-size:  1em;
    font-weight: bold;
  }

  .mh3 {
    color: #404040;
    font-size:  1em;
    font-weight: bold;
  }

  .system {
    font-family: monospace;
  }

  .file {
    font-family: monospace;
  }

  .jdkfile {
    font-family: monospace;
  }

  .code {
    font-family: monospace;
  }

  a {
    text-decoration: none;
  }

.jumpnav_my {
	background-color: #ffffee;
	border-bottom: 1px solid #cccccc;
	border-top: 1px solid #cccccc;
	border-left: 1px solid #cccccc;
	border-right: 1px solid #cccccc;
	padding: 5px;
	float: right;
	margin: 0px 5px 5px 5px;
	line-height: 1.5em;
}
.jumpnav_my ul {
	list-style: none;
	margin: 0;
	padding: 0;
}
.jumpnav_my ul ul {
	margin-left: 12px;
}

.interview {
	background-color: #ffffee;
	border-bottom: 1px solid #cccccc;
	border-top: 1px solid #cccccc;
	border-left: 1px solid #cccccc;
	border-right: 1px solid #cccccc;
	padding: 5px;
	line-height: 1.5em;
}
.interview ul {
	list-style: none;
	margin: 0;
	padding: 0;
}
.interview ul ul {
	margin-left: 12px;
}
li.answer {
        font-style: italic; 
        color: #115511; 
}
</style>

<title>HotSpot development on Linux with NetBeans - Part 2</title>

</head>

<body>

<div class="jumpnav_my">
<ul>
<li><bf>Contents</bf></li>
<li><a href="#"> </a>
  <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Prerequisites">Prerequisites </a>
   <ul>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Python">Python </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Mercurial">Mercurial</a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Forest">The Forest Extension </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Clone">Cloning the OpenJDK </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Freetype">Freetype </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Findbugs">Findbugs </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Cups">Cups </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Binaryplugs">Binary plugs </a></li>
   </ul>
  </li>
  <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Build">Building the OpenJDK </a>
   <ul>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#HotSpotBuild">Building the HotSpot </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#HotSpotRun">Running the HotSpot </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#CC_INTERP_Build">Building the C++-Interpreter </a></li>
   </ul>
  </li>
  <li><a href="#NetBeans">Developing with NetBeans</a>
   <ul>
    <li><a href="#NB_Clone">Cloning with NetBeans</a></li>
    <li><a href="#NB_CreateProject">Creating a HotSpot project</a></li>
    <li><a href="#NB_CodeAssistance">NetBeans Code Assistance </a></li>
    <li><a href="#NB_Debug">Debugging with NetBeans </a></li>
   </ul>
  </li>
  <li><a href="#Conclusion">Conclusion</a></li>
  <li><a href="#References">References</a></li>
</li>
</ul>
</div>

<p>
Here comes the second part of "HotSpot development on Linux with
NetBeans". While <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html">the first part</a> focused on building and running
the different flavors (opt/debug, client/server JIT compiler, template/C++
interpreter) of the HotSpot VM on Linux/x86, this second part concludes
with a short evaluation of NetBeans 6.0 as an development environment for
HotSpot hacking.
</p>

<a name="NetBeans"> </a>
<div class="mh2">Developing with NetBeans</div>

<p>
Now that we've successfully built the OpenJDK and know how we can efficiently
build and run the HotSpot, we are ready to start using <a href="http://www.netbeans.org">NetBeans</a> (NB for short) for HotSpot
development. Be sure to use at least version 6.0 if you want to do C/C++
development because starting with 6.0, NetBeans comes with builtin and highly
improved support for C/C++ projects that supersedes the old "cpp" and
"cpplite" modules which formed the NetBeans C/C++ Developer Pack (CND) in the
past. There's now a special <a href="http://download.netbeans.org/netbeans/6.0/final/">C/C++ Bundle</a>
available for download, that's only 11mb in size and contains all the needed
plugins for C/C++ development.
</p>

<p>
After installation, be sure you install the <a href="http://wiki.netbeans.org/wiki/view/MercurialVersionControl">Mercurial
plugin</a> by selecting <span class="code">Tools -&gt;Plugins -&gt;Available&#160;Plugins
-&gt;Mercurial</span>. You need to have Mercurial installed and available in
your <span class="code">PATH</span> for the Mercurial plugin to work (see <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Mercurial">Prerequisites - Mercurial</a>). If your Mercurial executable
isn't installed in a standard path or if you want to use a special Mercurial
version with the NB Mercurial plugin you can configure this under <span class="code">Tools
-&gt;Options -&gt;Versioning -&gt;Mercurial
-&gt;Mercurial&#160;Executable&#160;Path</span>.
</p>

<p>
You should note that if you are using NetBeans remotely (starting it on a
remote host and setting the DISPLAY variable to your local machine), you'll
probably want to set "<a href="http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.html#pixmaps">-Dsun.java2d.pmoffscreen=false</a>"
in the NetBeans configuration file
<span class="file">&lt;NB_directory&gt;/etc/netbeans.conf</span>. Without this setting, NB
was so slow for me that it was effectively unusable (e.g. opening the "File"
menu took about 20 seconds - every time!).
</p>

<a name="NB_Clone"> </a>
<div class="mh3">Cloning with NetBeans</div>

<p>
The nice thing about using NB for HotSpot development is that it has builtin
Mercurial support, so we don't need to use additional command line tools for
version control. Although we could start right away with the available HotSpot
sources from the previously cloned OpenJDK (see <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Clone">Cloning the
OpenJDK sources</a>) and have Mercurial support for it, we will instead clone
a brand new HotSpot repository from within NB to work with.
</p>

<p>
To achieve this we select <span class="code">Versioning -&gt;Mercurial
-&gt;Clone&#160;Other...</span>. In the appearing "Clone External Repository"
wizard, we enter <span class="file">http://hg.openjdk.java.net/jdk7/jdk7/hotspot</span> as
the "Repository URL" and a local "Parent Directory" and "Clone Name" (usually
<span class="file">hotspot</span>) for the new clone (don't forget to adjust the proxy
settings if necessary!). After clicking "Finish", NB will clone the HotSpot
sources to
<span class="file">&lt;Parent&#160;Directory&gt;/&lt;Clone&#160;Name&gt;</span>. For the
rest of this blog I'll assume that the HotSpot sources have been cloned to
<span class="file">/OpenJDK/jdk7/hotspot</span>. Here's the content of the Mercurial Output
window after a successful clone:
</p>

<pre class="listing">
Mercurial Clone
---------------
adding changesets
adding manifests
adding file changes
...
2895 files updated, 0 files merged, 0 files removed, 0 files unresolved
The number of output lines is greater than 500; see message log for complete output
INFO Clone From: http://hg.openjdk.java.net/jdk7/jdk7/hotspot
INFO To:         /OpenJDK/jdk7/hotspot

INFO: End of Clone
</pre>

<p>
Now that we have cloned a fresh repository, we should not forget to patch the
sources with the <a href="http://weblogs.java.net/blog/simonis/patch/linux32.patch/linux32.patch">patch
file</a> that has been <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#Linux_Patch">previously described</a> in
order to work around some build problems.
</p>

<a name="NB_CreateProject"> </a>
<div class="mh3">Creating a HotSpot project</div>

<p>
With the newly cloned HotSpot sources, we are ready to create a NetBeans
project for HotSpot. We more or less follow the description of "<a href="http://www.netbeans.org/kb/60/cnd/quick-start.html#makefileprojects">Creating
a C/C++ Project From Existing Code
</a>" in the NB Quick Start tutorial, but as you'll see, there are quite some
intricate issues you need to consider here, in order to get a working HotSpot
project.
</p>

<p>
First we start the "New Project" wizard by going to <span class="code">File
-&gt;New&#160;Project</span>. In the "New Project" wizard we select "C/C++
Project From Existing Code" as project type. In the next step, we select
"Using an existing makefile" and enter
<span class="file">/OpenJDK/jdk7/hotspot/make/Makefile</span> as the project makefile. In
the following "Build Actions" step, we have to specify the project's "Working
Directory". The presetting <span class="file">/OpenJDK/jdk7/hotspot/make</span> (i.e. the
directory that contains the makefile we've just specified in the previous
step) will not work here because of a NB bug (see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=125214">Issue
125214</a>). We have to use the HotSpot root directory
(i.e. <span class="file">/OpenJDK/jdk7/hotspot</span> in our case) in order to work around
this problem.
</p>

<p>
Next we have to define the right "Build Command" which is a little bit tricky,
because we've just selected the HotSpot root directory as our working
directory. So the first thing we have to do in the "Build Command", will be to
change into the <span class="file">make/</span> directory. As real build command we can use
a command line similar to the ones we used in the <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#HotSpotBuild">Building the HotSpot</a> section. And although the build
output will be captured in the NB "Build Output Window", it may be still a good
idea to additionally store it in a file. So here's a first version of the
"Build Command":
</p>

<pre class="listing">
cd make &amp;&amp; LANG=C ALT_BOOTDIR=/share/software/jse/1.6.0/ ALT_OUTPUTDIR=../../hotspot_c2_debug \
make jvmg 2&gt;&amp;1 | tee ../../hotspot_c2_debug.log
</pre>

<p>
But wait, there's another problem in NB with VERY long lines in the "Build
Output Window" (see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=124796">Issue
124796</a>): if a line exceeds 32Kb, the output will stop and the build will
freeze! Unfortunately, the HotSpot Makefile indeed produces a VERY HUGE line:
the command line which is created by the makefiles to compile the Java sources
of the Serviceability Agent may exceed 100Kb (depending on the absolute base
path of your HotSpot sources). With the additional filter part which is needed
to strip this huge line from the output, our build command looks as follows:
</p>

<pre class="listing">
cd make &amp;&amp; LANG=C ALT_BOOTDIR=/share/software/jse/1.6.0/ ALT_OUTPUTDIR=../../hotspot_c2_debug \
make jvmg 2&gt;&amp;1 | grep -v "javac \-source 1\.4" | tee ../../hotspot_c2_debug.log
</pre>

<p>
The clean command is easier - we just have to call the "clean"
target. Nevertheless we have to specify <span class="code">ALT_OUTPUTDIR=</span> on the
command line such that <span class="code">make</span> knows which directory we want to
clean:
</p>

<pre class="listing">
cd make &amp;&amp; ALT_OUTPUTDIR=../../hotspot_c2_debug make clean
</pre>

<p>
We leave the "Build Result" field empty for now, because the directories which
will contain the build results don't exist until now anyway and NB will
complain about this fact. Later on, after we have build the project for the
first time, it will be possible to adjust this setting easily.
</p>

<p>
The next step in the "New Project" wizard requires the specification of the
folders which contain files that should be added to the project. Again, the
"Working Directory" specified in a previous step is the predefined default
setting for this entry. Because we have already set the "Working Directory" to
point to the HotSpot root directory, this presetting is ok for now. <a href="#NB_AddFiles">Later on</a> we can (and we will) add additional source
folders for the files which were automatically generated by the HotSpot make
to the project. We can also restrict the "File types" to "<span class="file">.c .cpp .h
.hpp .ad</span>", because these file types are probably the only ones we will
be interested in (<span class="file">.ad</span> is the extension for so called "<a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/src//share/vm/adlc/Doc/Syntax.doc">Architecture
Description</a>" files which are not real C/C++ files, but contain C/C++ code
which is used to automatically generate some other source files, so it is
probably a good idea to have them in the project).
</p>

<p>
We will skip the "<a href="#NB_CodeAssistance">Code Assistance
Configuration</a>" for now and come back later to it. In the final project
configuration step we'll have to choose a name for our project
(i.e. <span class="file">hotspot_NB</span>) and a directory (the "Project Location") where
NetBeans will save its project folder. Because I don't like to clutter my
version controlled directories with external files, I usually place the
project directory parallel to the project's root directory (i.e. into
<span class="file">/OpenJDK/jdk7</span> in this example). But that's up to the user. It may
be for example a good idea (once the things have settled down) to place a
generic NetBeans project directory (you can find such pre-configured projects
for Solaris <a href="http://cnd.netbeans.org/docs/hotspot-projects/">here</a>)
inside the HotSpot make directory. In such a case, NB could automatically
detect and open the project during the cloning process (this is an option which
can be activated with a check box in the <a href="#NB_Clone">Mercurial Cloning
Wizard</a>).
</p>

<p>
After we have created the new project, we can open the context menu of the
project in the "Projects" view and select the "Build" action. This will start
the HotSpot build and log all the build output to the "Build Output
Window". The build command that was specified in the previous step will only
build the server version of the HotSpot VM. If we want to build different
versions of the VM (with C1 or C2 JIT compiler, with template or C++
interpreter, debug, optimized or product versions) we can create different
project configurations for each version by selecting
<span class="code">Set&#160;Configuration -&gt;Manage&#160;Configurations...</span> from
the project's context menu. In the appearing "Project Properties" window, we
press the <span class="code">Manage&#160;Configurations...</span> button and get the
"Configurations" window. Here we can rename our current configuration to "C2
debug" (because it builds a debug version of the HotSpot with the C2 server
compiler) and make a copy of "C2 debug" which we rename to "C1 debug" (this
will be the configuration for building a debug VM with the C1 client
compiler). After we return to the "Project Properties" window by pressing
<span class="code">OK</span>, we can select the "C1 debug" configuration and adapt the
build and clean commands accordingly (originally they are just copies of the
corresponding commands from the "C2 debug" configuration). For building the
"C1 debug" configuration, we could set them as follows:
</p>

<pre class="listing">
cd make &amp;&amp; LANG=C ALT_BOOTDIR=/share/software/jse/1.6.0/ ALT_OUTPUTDIR=../../hotspot_c1_debug \
make jvmg1 2&gt;&amp;1 | grep -v "javac \-source 1\.4" | tee ../../hotspot_c1_debug.log
</pre>

<pre class="listing">
cd make &amp;&amp; ALT_OUTPUTDIR=../../hotspot_c1_debug make clean
</pre>

<p>
With the knowledge from the <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#HotSpotBuild">Building the HotSpot</a>
section, it should be easy to create all the required, additional
configurations accordingly. Notice however, that it may be a good idea to first
complete the Code Assistance configuration described in the next section
before cloning a configuration. This will save you a lot of time because most
of the Code Assistance settings can be shared across configurations.
</p>

<a name="NB_CodeAssistance"> </a>
<div class="mh3">NetBeans Code Assistance</div>

<p>
After we have successfully built the HotSpot project for the first time, it is
necessary to refine the project settings. This is because the HotSpot is a
quite unusual project in the sense that it has a different source structure
than most open source C/C++ projects and therefore doesn't fit right away into
a NetBeans project.
</p>

<p>
As you probably realized already, the HotSpot source tree contains sources for
different operating systems and processor architectures. These different files
often contain classes and functions with the same names for different
platforms. This isn't a problem during the build because the build process
figures out the current platform and only considers the needed files. But it
considerably confuses the NB Code Assistance to have more than one class or
method definition with the same name. Therefore, my advice is to remove the
unused platform files from the project. This has the additional benefit of
speeding up the parsing of a project at startup, because the project will
contain considerably fewer files. If we build on Linux/x86, the following
files and directories can be safely removed from the project (right click the
corresponding file/directory items in the "Project View" and choose "Remove"):
</p>

<pre class="listing">
hotspot/agent/src/os/solaris
hotspot/agent/src/os/win32
hotspot/agent/src/share/native/jvmdi
hotspot/src/cpu/sparc
hotspot/src/os/solaris
hotspot/src/os/windows
hotspot/src/os_cpu/solaris_sparc
hotspot/src/os_cpu/solaris_x86
hotspot/src/os_cpu/windows_x86
hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp
hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp
</pre>

<p>
In the past, the JDK contained the two distinct subdirectories
<span class="file">i486</span> and <span class="file">amd64</span> for 32-bit and 64-bit x86
architectures respectively. Now, these two architectures have been merged into
the single subdirectory <span class="file">x86</span>. However, because the
<span class="file">x86</span> subdirectory still contains files which are relevant for only
one of the two architectures, we can also remove the following files from the
project on a 32-bit Linux system:
</p>

<pre class="listing">
hotspot/src/cpu/x86/vm/assembler_x86_64.cpp
hotspot/src/cpu/x86/vm/assembler_x86_64.hpp
hotspot/src/cpu/x86/vm/assembler_x86_64.inline.hpp
hotspot/src/cpu/x86/vm/dump_x86_64.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp
hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp
hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp
hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp
hotspot/src/cpu/x86/vm/runtime_x86_64.cpp
hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
hotspot/src/cpu/x86/vm/stubRoutines_x86_64.cpp
hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp
hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
hotspot/src/cpu/x86/vm/templateTable_x86_64.hpp
hotspot/src/cpu/x86/vm/vm_version_x86_64.cpp
hotspot/src/cpu/x86/vm/vm_version_x86_64.hpp
hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp
hotspot/src/cpu/x86/vm/x86_64.ad
hotspot/src/os_cpu/linux_x86/vm/assembler_linux_x86_64.cpp
hotspot/src/os_cpu/linux_x86/vm/linux_x86_64.ad
hotspot/src/os_cpu/linux_x86/vm/linux_x86_64.s
</pre>


<a name="NB_AddFiles"> </a>
<p>
Another peculiarity of HotSpot is the fact that it creates source files during
the build process. These files are placed into the sub-folder
<span class="file">&lt;os&gt;_&lt;arch&gt;_compiler&lt;1|2&gt;/generated</span> of the
specified output folder
(i.e. <span class="file">/OpenJDK/jdk7/hotspot_c2_debug/linux_i486_compiler2/generated</span>
in our example). Among others, these are mainly the files generated by the ADL
compiler from the <span class="file">.ad</span> file in the
<span class="file">&lt;os&gt;_&lt;arch&gt;_compiler&lt;1|2&gt;/generated/adfiles</span>
subdirectory and the include files generated by <span class="file">MakeDeps</span> from the
"includeDB" files in the
<span class="file">&lt;os&gt;_&lt;arch&gt;_compiler&lt;1|2&gt;/generated/incls</span>
subdirectory. (Notice that the "includeDB" technique is another undocumented,
HotSpot specific trickery that's beyond the scope of this introduction. You
can find a minimalistic introduction at the top of
<a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/src/share/vm/includeDB_core" class="jdkfile">hotspot/src/share/vm/includeDB_core</a>)
</p>

<p>
In the next step, we will therefore add the to two subdirectories
<span class="file">generated/adfiles/</span> and <span class="file">generated/incls/</span> from within
the output folder to the sources of our project by selecting
<span class="code">Add&#160;Existing&#160;Items&#160;from&#160;Folders...</span> from the
project's context menu. Don't forget to use <span class="file">.c .cpp .h .hpp .incl</span>
as "File types" because the include files generated by <span class="file">MakeDeps</span>
all have <span class="file">.incl</span> suffixes.  We'll also have to tell NetBeans to
treat files with a <span class="file">.incl</span> suffix like usual C/C++ header files by
going to <span class="code">Tools -&gt;Options -&gt;Advanced&#160;Options
-&gt;IDE&#160;Configuration -&gt;System -&gt;Object&#160;Types
-&gt;C&#160;and&#160;C++&#160;Header&#160;Data&#160;Objects</span> and add
<span class="file">incl</span> as extension in the
<span class="code">Extension&#160;and&#160;MIME&#160;Types</span> field.
</p>

<p>
Once we have added all the additional files to our project, we can start
configuring the NetBeans Code Assistance. There are two main points that have
to be done here: first we have to specify the directories where the Code
Assistance parser should look for include files and second we have to define
the preprocessor directives which should be considered during code parsing. For
the first step we have to go to <span class="code">Project&#160;Properties
-&gt;Code&#160;Assistance -&gt;C++&#160;Compiler
-&gt;Include&#160;Directories</span>. Unfortunately it is only possible to add
one directory at a time from the file selection box and there are quite some
directories we have to add:
</p>

<pre class="listing">
hotspot/src/share/vm/adlc
hotspot/src/share/vm/asm
hotspot/src/share/vm/c1
hotspot/src/share/vm/ci
hotspot/src/share/vm/classfile
hotspot/src/share/vm/code
hotspot/src/share/vm/compiler
hotspot/src/share/vm/gc_implementation
hotspot/src/share/vm/gc_implementation/concurrentMarkSweep
hotspot/src/share/vm/gc_implementation/parNew
hotspot/src/share/vm/gc_implementation/parallelScavenge
hotspot/src/share/vm/gc_implementation/shared
hotspot/src/share/vm/gc_interface
hotspot/src/share/vm/interpreter
hotspot/src/share/vm/libadt
hotspot/src/share/vm/memory
hotspot/src/share/vm/oops
hotspot/src/share/vm/opto
hotspot/src/share/vm/prims
hotspot/src/share/vm/runtime
hotspot/src/share/vm/services
hotspot/src/share/vm/utilities
hotspot/src/cpu/x86/vm/
hotspot/src/os/linux/launcher/
hotspot/src/os/linux/vm/
hotspot/src/os_cpu/linux_x86/vm/
../hotspot_c2_debug/linux_i486_compiler2/generated/
../hotspot_c2_debug/linux_i486_compiler2/generated/adfiles/
../hotspot_c2_debug/linux_i486_compiler2/generated/jvmtifiles/
</pre>

<p>
After we've added the required include directories, we have to tell the Code
Assistance parser which preprocessor definitions it should use when parsing
the project. For the time being, I just took a look at the compilation
command line of some arbitrary HotSpot files, copied all the definitions they
contained and inserted them into the
<span class="code">Preprocessor&#160;Definitions</span> field:
</p>

<pre class="listing">
LINUX _GNU_SOURCE IA32 ASSERT DEBUG COMPILER2 COMPILER1 _REENTRANT VM_LITTLE_ENDIAN GAMMA
</pre>

<p>
Because I was not sure if Code Assistance would parse <span class="file">.h</span> as C or
as C++ files, I doubled the values for
<span class="code">Include&#160;Directories</span> and
<span class="code">Preprocessor&#160;Definitions</span> in the <span class="code">C&#160;Compiler</span>
section. If you prefer typing instead of clicking, you can also edit the
project's configurations file
<span class="file">&lt;NB_project_dir&gt;/nbproject/configurations.xml</span> by hand
and simply duplicate the entries inside the
<span class="code">&lt;ccCompilerTool&gt;</span> tag for the
<span class="code">&lt;cCompilerTool&gt;</span> tag. As you can see, the enclosing
<span class="code">&lt;confs&gt;</span> tag contains all the relevant configuration
settings for a project:
</p>

<pre class="listing">
  &lt;projectmakefile&gt;hotspot_NB-Makefile.mk&lt;/projectmakefile&gt;
  &lt;confs&gt;
    &lt;conf name="C2_debug" type="0"&gt;
      &lt;toolsSet&gt;
        &lt;compilerSet&gt;GNU&lt;/compilerSet&gt;
        &lt;cRequired&gt;true&lt;/cRequired&gt;
        &lt;cppRequired&gt;true&lt;/cppRequired&gt;
        &lt;fortranRequired&gt;false&lt;/fortranRequired&gt;
        &lt;platform&gt;2&lt;/platform&gt;
      &lt;/toolsSet&gt;
      &lt;makefileType&gt;
        &lt;makeTool&gt;
          &lt;buildCommandWorkingDir&gt;../hotspot&lt;/buildCommandWorkingDir&gt;
          &lt;buildCommand&gt;cd make &amp;&amp; 
            LANG=C
            ALT_BOOTDIR=/share/software/jse/1.6.0/
            ALT_OUTPUTDIR=../../hotspot_c2_debug 
            make jvmg 2&gt;&amp;1 | 
            grep -v "javac \-source 1\.4"  | tee ../../hotspot_c2_debug.log
          &lt;/buildCommand&gt;
          &lt;cleanCommand&gt;cd make &amp;&amp; 
            ALT_OUTPUTDIR=../../hotspot_c2_debug make clean
          &lt;/cleanCommand&gt;
          &lt;executablePath&gt;
            ../hotspot_c2_debug/linux_i486_compiler2/jvmg/gamma
          &lt;/executablePath&gt;
          &lt;cCompilerTool&gt;
            &lt;includeDirectories&gt;
              &lt;directoryPath&gt;../hotspot/src/cpu/x86/vm&lt;/directoryPath&gt;
              &lt;directoryPath&gt;../hotspot/src/os/linux/launcher&lt;/directoryPath&gt;
              &lt;directoryPath&gt;../hotspot/src/os/linux/vm&lt;/directoryPath&gt;
              ...
            &lt;/includeDirectories&gt;
            &lt;preprocessor&gt;LINUX _GNU_SOURCE IA32 ASSERT DEBUG COMPILER2
              COMPILER1 _REENTRANT VM_LITTLE_ENDIAN GAMMA
            &lt;/preprocessor&gt;
          &lt;/cCompilerTool&gt;
          &lt;ccCompilerTool&gt;
            &lt;includeDirectories&gt;
              &lt;directoryPath&gt;../hotspot/src/cpu/x86/vm&lt;/directoryPath&gt;
              &lt;directoryPath&gt;../hotspot/src/os/linux/launcher&lt;/directoryPath&gt;
              &lt;directoryPath&gt;../hotspot/src/os/linux/vm&lt;/directoryPath&gt;
              ...
            &lt;/includeDirectories&gt;
            &lt;preprocessor&gt;LINUX _GNU_SOURCE IA32 ASSERT DEBUG COMPILER2
              COMPILER1 _REENTRANT VM_LITTLE_ENDIAN GAMMA
            &lt;/preprocessor&gt;
          &lt;/ccCompilerTool&gt;
        &lt;/makeTool&gt;
        &lt;requiredProjects&gt;
        &lt;/requiredProjects&gt;
      &lt;/makefileType&gt;
</pre>

<p>
Of course, manual changes to the project's configurations file should only be
done if a project isn't active in a running NetBeans session! Notice that the
parsing of a project like HotSpot may take a considerable amount of time - on
my machine about 60 seconds. The progress of this operation is indicated by a
small progress bar in the lower right corner of NB. Clicking on it will open a
small window which logs the files that are currently processed by the Code
Assistance parser. NetBeans parses a project every time the project is
opened. Although this may take some time, I think this was the right decision,
because this way there's no database file on disk that can get corrupted. If
you should encounter problems with Code Assistance (see below), you'll just
have to close and reopen the accountable project, to hopefully get it working
again.
</p>

<p>
During my first configuration attempts, I sometimes got null pointer
exceptions during code parsing (see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=125611">issue 125611</a>)
and once Code Configuration didn't complete at all. However, once I figured out
and set up the right Code Assistance settings (especially the right include
paths and preprocessor directives), Code Assistance ran quite
smooth. Especially the possibility of defining different project
configurations with different preprocessor directives (opt vs. debug, template
vs. C++ interpreter) and include paths and easily switching between these
configurations while the source information is always accurate, is quite nice.
</p>

<a name="NB_Debug"> </a>
<div class="mh3">Debugging with NetBeans</div>

<p>
After I had finally finished the "Code Assistance" configuration I was keen on
trying the debugging support in NetBeans. I first went to the
<span class="code">Project&#160;Properties -&gt;Make</span> and changed the
<span class="code">Build&#160;Results</span> entry to point to the <span class="file">gamma</span>
executable in the output directory
(<span class="file">../hotspot_c2_debug/linux_i486_compiler2/jvmg/gamma</span> in this
example). Notice that this will always be a relative path with respect to your
project directory if you choose the executable with the file selection
box. The only way to enter an absolute path name here is by entering it
manually into the text field (you'll have to do this if you choose to use
another <span class="code">Run&#160;Directory</span> than the default project directory in
the next step).
</p>

<p>
In the <span class="code">Running</span> category of the
<span class="code">Project&#160;Properties</span>, I entered "<span class="code">-XX:+TraceBytecodes
-XX:StopInterpreterAt=1 -version</span>" for the <span class="code">Arguments</span> and
added <span class="code">JAVA_HOME</span> and <span class="code">LD_LIBRARY_PATH</span> to the
<span class="code">Environment</span> with the values as described in <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html#HotSpotRun">Running the HotSpot</a>. If you don't set the
<span class="code">Run&#160;Directory</span>, the NB project directory will be used as a
default. If you choose another <span class="code">Run&#160;Directory</span> you need to set
<span class="code">Build&#160;Results</span> in the <span class="code">Make</span> category such that it
contains the absolute path to the executable, in order to run it successfully.
</p>

<p>
With these settings, it was possible to run the HotSpot by executing the
<span class="code">Run&#160;Main&#160;Project</span> action. This will open a fresh
<span class="code">xterm</span> window, dump the executed bytecodes (because of the
<span class="code">-XX:+TraceBytecodes</span> option) and finally print out the version of
the VM and the Java Runtime Environment:
</p>

<pre class="listing">
...
[4506] virtual void java.io.FileOutputStream.write(jobject, jint, jint)
[4506]   385353     0  fast_aload_0
[4506]   385354     1  aload_1
[4506]   385355     2  iload_2
[4506]   385356     3  iload_3
[4506]   385357     4  invokespecial 5376 &lt;writeBytes&gt; &lt;([BII)V&gt;
OpenJDK Runtime Environment (build 1.7.0-internal-debug-dXXXXXX_04_jan_2008_11_27-b00)
...
[4506] virtual void java.io.FileOutputStream.write(jobject, jint, jint)
[4506]   390343     0  fast_aload_0
[4506]   390344     1  aload_1
[4506]   390345     2  iload_2
[4506]   390346     3  iload_3
[4506]   390347     4  invokespecial 5376 &lt;writeBytes&gt; &lt;([BII)V&gt;
OpenJDK Server VM (build 12.0-b01-internal-jvmg, mixed mode)[4506]   390348     7  return
...
392702 bytecodes executed in 229.6s (0.002MHz)
</pre>

<p>
As you can see, printing the OpenJDK version requires the execution of nearly
400.000 bytecodes, so think twice before before you heedlessly call
<span class="code">java&#160;-version</span> the next time:) 
</p>

<p>
Now that we successfully run the HotSpot within NetBeans, we can set up a
breakpoint and try the debugger. Please be sure to use at least gdb 6.6,
otherwise the NetBeans gdb-plugin will <a href="http://www.netbeans.org/issues/show_bug.cgi?id=125932">abort the
debugging session</a> because of warnings which are thrown by older versions
of gdb when debugging the HotSpot. Notice that you can not specify which gdb
version to use in NetBeans. Instead you have to set the executable path (under
<span class="code">Tools -&gt;Options -&gt;C/C++ -&gt;Build&#160;Tools
-&gt;Current&#160;Path</span>) such that the desired version of gdb will be
detected first by NB.
</p>

<p>
The <span class="code">-XX:StopInterpreterAt=&lt;<it>n</it>&gt;</span> option can
be used to stop the HotSpot interpreter before the execution of the specified
bytecode number. It is implemented by continuously counting each executed
bytecode until the <it>n</it>-th bytecode is reached at which point the
VM will call the global, empty <span class="code">breakpoint()</span> function. This
<span class="code">breakpoint()</span> function is a hook for the debugger which can be
used to intercept the execution of the specified bytecode by defining a debugger,
breakpoint for it. We choose <span class="code">Run -&gt;New&#160;Breakpoint...</span> and
enter <span class="code">breakpoint</span> as the <span class="code">Function&#160;Name</span>. Then we
execute <span class="code">Debug&#160;Main&#160;Project</span> to debug the project. This
time, only the first bytecode will be printed in the output window and the
HotSpot will stop in the <span class="code">breakpoint()</span> function:
</p>

<pre class="listing">
VM option '+TraceBytecodes'
VM option 'StopInterpreterAt=1'

[5027] static void java.lang.Object.&lt;clinit&gt;()
[5027]        1     0  invokestatic 2304 &lt;registerNatives&gt; &lt;()V&gt; 
</pre>

<p>
Unfortunately, that's basically all we can currently do with the debugger
support in NetBeans. If we have a look at the stack in the <span class="code">Call
Stack</span> window, we can see something similar to:
</p>

<pre class="listing">
#0  breakpoint ()
    at /OpenJDK/jdk7/hotspot/src/os/linux/vm/os_linux.cpp:394
#1  0x0665d5f5 in os::breakpoint ()
    at /OpenJDK/jdk7/hotspot/src/os/linux/vm/os_linux.cpp:389
#2  0x40246164 in ?? ()
#3  0xbfffb658 in ?? ()
#4  0x43316097 in ?? ()
#5  0xbfffb67c in ?? ()
#6  0x43375ab8 in ?? ()
</pre>

<p>
The unknown frames are neither a debugger nor a NetBeans problem. It's just
the result of the fact that the HotSpot is more than often in generated
code. This is true for both interpreters, the template interpreter as well
as for the C++ interpreter to a certain degree, and of course for compiled
(JITed) code. Unfortunately, the NB debugger support can not handle assembler
(e.g. there is no <span class="code">stepi</span> command, no register window and no
assembler code view). Moreover, signal handling is not implemented (crucial for
HotSpot debugging) and the thread support doesn't work either. Generally
speaking, the debugging support in NetBeans is quite basic right now and only
useful for debugging not deeper than to the C/C++ level.
</p>

<p>
Probably I should have read the NetBeans <a href="http://cnd.netbeans.org/gdb-debugger-milestones.html">GDB Debugger
Milestones</a> before starting. It lists all the missing features for future
milestones. By private communication with some NB developers (thanks to Leonid
Lenyashin and Sergey Grinev) I also got the information that the
<span class="code">dbx</span>-engine already has disassembler support, stepi, a register
view and it works well with multiple threads. However, the
<span class="code">dbx</span>-engine is currently only available in <a href="http://developers.sun.com/sunstudio/">Sun Studio</a> which at the time
of this writing is still NetBeans 5.5.1 based (although there should be a new
NB 6 based express release in couple of weeks). I did some quick experiments
and the dbx-engine looks indeed promising, but dbx had problems with the debug
information generated by g++, so I gave up. Perhaps I'll try again with the
next Sun Studio release that can read my NetBeans 6 project files.
</p>


<p>
I also had the chance to ask <a href="http://blogs.sun.com/SDNChannel/entry/the_new_face_of_sun">Gordon
Prieur</a>, a Sun staff engineer and project lead for Sun Studio IDE some
questions about the status of the NetBeans gdb debugging engine. Following you
can find his answers:
</p>

<div class="interview">
<ul>
<li>
NetBeans has no gdb command line (how do I send a command (like for
example "stepi" or "x /8i $pc") that is not supported from the Debugger Menu
or Debugger Toolbar to gdb)
</li>
<ul>
<li class="answer">
There are 2 issues in this question. One has to do with the gdb module missing
features. The other with adding command-line support. I'll answer these separately.
</li>
<ul>
<li class="answer">
   o Missing features (specifically "stepi" and "x ..."): There is currently no support
      in the module for assembly level debugging. Some assembly support is being
      added in NB 6.1 (Leonid can give you more details about this than I can) but
      assembly level debugging won't make it into 6.1. Hopefully it will be part of
     7.0. I would expect stepi and x type commands would be part of this.
</li>
<li class="answer">
   o GDB Command-line: This is unlikely to ever be publicly available. The problem
     is that too many gdb command-line commands change state which the NetBeans
     gdb module wouldn't know about. To correctly support this we'd either need to
     process all typed commands before sending them to gdb, or to have gdb tell us
     any time a command-line change affects us.
</li>
</ul>
</ul>
<li>
The "Thread View" is not working (it shows no output at all)
</li>
<ul>
<li class="answer">
This feature is being added in NB 6.1
</li>
</ul>
<li>
There is no register windows that displays the native registers (and I can not print them manually either because of point 1.)
</li>
<ul>
<li class="answer">
A register window has been considered but is not yet planned for a specific release.
Its very possible it will be done when we add assembly debugging support.
</li>
</ul>
<li>
If I get a warning from gdb (e.g. "Previous frame inner to this frame (corrupt
stack?)") the NB debugging session is aborted (see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=125932">issue
125932</a>). This should be handled more gracefully.
</li>
<ul>
<li class="answer">
In general, errors/warnings like this happen when gdb (the debugger, not the gdb module)
dumps core or is no longer usable. I don't see any more graceful way of handling a gdb
core dump. I'm definitely open to suggestions on how it can be handled...
</li>
</ul>
</ul>
</div>

<p/>

<a name="Conclusion"> </a>
<div class="mh2">Conclusion</div>

<p>
Congratulation! If you really read all this blog from the beginning up to here
please <a href="mailto:volker.simonis@gmail.com?subject=I got the party started!">drop me a note</a>. Hopefully you managed to successfully build and
run the HotSpot on Linux!
</p>

<p>
Although this tutorial got quite lengthy in the end, building and running an
own version of OpenJDK and the HotSpot VM should be not to hard for any
developer with average Linux experience. Depending on the Linux distribution,
there will probably always be the need to install some newer and sometimes
even some older version (e.g. gcc) of some packages to meet the build
requirements of the OpenJDK - but that should be manageable.
</p>

<p>
Regarding NetBeans, there's no clear recommendation from my side. If you're
already familiar with an IDE like NetBeans, it my be worth while going through
all the project configuration hassle to get the integrated Mercurial support
and a reasonably well working Code Assistance - but you will still have to use
the command line for debugging. On the other side, if you're already using <a href="http://www.gnu.org/software/emacs/">Emacs</a> with <a href="http://cscope.sourceforge.net/">Cscope</a> and <a href="http://www.xsteve.at/prg/emacs_dvc/dvc.html">DVC</a> there's probably no
killer argument for switching to NetBeans for HotSpot development.
</p>

<a name="References"> </a>
<div class="mh2">References</div>

<p>

[1] <a href="http://weblogs.java.net/blog/kellyohair/archive/2006/12/jdk6_build_chea.html">Kelly
O'Hair's Build Cheat Sheet</a>
<br/>

[2] <a href="http://blogs.sun.com/kto/entry/glossary_for_jdk_builds">Kelly
O'Hair's Glossary for JDK Builds</a>
<br/>

[3] <a href="http://hg.openjdk.java.net/jdk7/jdk7/raw-file/jdk7-b24/README-builds.html">OpenJDK
Build Readme</a>
<br/>

[4] <a href="http://www.netbeans.org/kb/60/cnd/quick-start.html">NetBeans
C/C++ Support Quick Start Tutorial</a>
<br/>


[5] <a href="http://blogs.sun.com/SDNChannel/entry/the_new_face_of_sun">Interview
with Gordon Prieur about Sun Studio 12
</a>
<br/>

</p>

</body>
</html>]]>

</content>
</entry>
<entry>
<title>HotSpot development on Linux with NetBeans - Part 1</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html" />
<modified>2008-01-25T01:16:47Z</modified>
<issued>2008-01-25T00:31:59Z</issued>
<id>tag:weblogs.java.net,2008:/blog/simonis/427.9053</id>
<created>2008-01-25T00:31:59Z</created>
<summary type="text/plain">Here comes yet another step-by-step tutorial which explains how to fetch the
OpenJDK sources, compile them and work with them inside the NetBeans IDE. It
focuses on building and running the different flavors (opt/debug,
client/server JIT compiler, template/C++ interpreter) of the HotSpot VM on
Linux/x86 and concludes with a short evaluation of NetBeans 6.0 as an
development environment for HotSpot hacking.</summary>
<author>
<name>simonis</name>

<email>volker.simonis@gmail.com</email>
</author>
<dc:subject>Community: OpenJDK</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/simonis/">
<![CDATA[<html>

<head>

<style type="text/css" id="internalStyle">
  body {
    font-family: arial, helvetica, sans-serif;
    font-size: 10pt;
  }

  pre.listing {
    display: table;
    color: black;
    background-color: lightgray;
    border-style: solid;
    border-width: 1px;
    border-color: darkgray;
    margin: 8px 0px 5px 0px;
    padding: 2px;
    width: auto; 
    overflow: auto;  
    font-family: monospace;
  }

  .warning {
    color: red;
    font-size:  0.8em;
    text-align: center;
  }

  .mh1 {
    color: #202080;
    font-size:  1.2em;
    font-weight: bold;
  }

  .mh2 {
    color: #202080;
    font-size:  1em;
    font-weight: bold;
  }

  .mh3 {
    color: #404040;
    font-size:  1em;
    font-weight: bold;
  }

  .system {
    font-family: monospace;
  }

  .file {
    font-family: monospace;
  }

  .jdkfile {
    font-family: monospace;
  }

  .code {
    font-family: monospace;
  }

  a {
    text-decoration: none;
  }

.jumpnav_my {
	background-color: #ffffee;
	border-bottom: 1px solid #cccccc;
	border-top: 1px solid #cccccc;
	border-left: 1px solid #cccccc;
	border-right: 1px solid #cccccc;
	padding: 5px;
	float: right;
	margin: 0px 5px 5px 5px;
	line-height: 1.5em;
}
.jumpnav_my ul {
	list-style: none;
	margin: 0;
	padding: 0;
}
.jumpnav_my ul ul {
	margin-left: 12px;
}

.interview {
	background-color: #ffffee;
	border-bottom: 1px solid #cccccc;
	border-top: 1px solid #cccccc;
	border-left: 1px solid #cccccc;
	border-right: 1px solid #cccccc;
	padding: 5px;
	line-height: 1.5em;
}
.interview ul {
	list-style: none;
	margin: 0;
	padding: 0;
}
.interview ul ul {
	margin-left: 12px;
}
li.answer {
        font-style: italic; 
        color: #115511; 
}
</style>

<title>HotSpot development on Linux with NetBeans - Part 1</title>

</head>

<body>

<div class="jumpnav_my">
<ul>
<li><bf>Contents</bf></li>
<li><a href="#"> </a>
  <li><a href="#Prerequisites">Prerequisites </a>
   <ul>
    <li><a href="#Python">Python </a></li>
    <li><a href="#Mercurial">Mercurial</a></li>
    <li><a href="#Forest">The Forest Extension </a></li>
    <li><a href="#Clone">Cloning the OpenJDK </a></li>
    <li><a href="#Freetype">Freetype </a></li>
    <li><a href="#Findbugs">Findbugs </a></li>
    <li><a href="#Cups">Cups </a></li>
    <li><a href="#Binaryplugs">Binary plugs </a></li>
   </ul>
  </li>
  <li><a href="#Build">Building the OpenJDK </a>
   <ul>
    <li><a href="#HotSpotBuild">Building the HotSpot </a></li>
    <li><a href="#HotSpotRun">Running the HotSpot </a></li>
    <li><a href="#CC_INTERP_Build">Building the C++-Interpreter </a></li>
   </ul>
  </li>
  <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html">Developing with NetBeans</a>
   <ul>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html#NB_Clone">Cloning with NetBeans</a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html#NB_CreateProject">Creating a HotSpot project</a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html#NB_CodeAssistance">NetBeans Code Assistance </a></li>
    <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html#NB_Debug">Debugging with NetBeans </a></li>
   </ul>
  </li>
  <li><a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html#Conclusion">Conclusion</a></li>
  <li><a href="#References">References</a></li>
</li>
</ul>
</div>

<p>
Here comes yet another step-by-step tutorial which explains how to fetch the
OpenJDK sources, compile them and work with them inside the NetBeans IDE. It
focuses on building and running the different flavors (opt/debug,
client/server JIT compiler, template/C++ interpreter) of the HotSpot VM on
Linux/x86 and concludes with a short evaluation of NetBeans 6.0 as an
development environment for HotSpot hacking. 
</p>

<p>
Because it was two big for a single blog entry, it is split up into two parts:
this first part explains how to build and run the HotSpot while the NetBeans
integration is described in the <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html">second part</a>.
</p>

<p>
If you're interested in building on Windows you can consult <a href="http://blogs.tedneward.com/2007/12/15/Let+The+JDK+Hacking+Begin.aspx">Ted
Nedwards blog</a>. A description of how to build different Java-only parts of
the JDK with NetBeans 6 can be found <a href="http://nb-openjdk.netbeans.org/get-and-build.html">here</a> (note that
the current NetBeans "world" project under jdk/make/netbeans which is supposed to
build the entire JDK (including the HotSpot) doesn't work anymore after the
Mercurial switch and the resulting directory restructuring).
</p>

<a name="Prerequisites"> </a>
<div class="mh2">Prerequisites - Mercurial, Forest extension, Freetype, Findbugs, CUPS</div>



<p>
I started to develop on a Suse Enterprise Linux 9.3 server with 4 Intel Xeon
CPUs at 3GHz with 4GB of memory. It had gcc 3.3.3 and gnumake 3.80 installed
by default which both suffice for OpenJDK development.
</p>

<p>
The following subsections will detail how I installed various required
software packages. I usually compile and install new software into
<span class="file">/share/software</span> and link the resulting executables to
<span class="file">/usr/local/bin</span> which comes first in my <span class="file">PATH</span>
environment variable.
</p>

<a name="Python"> </a>
<div class="mh3">Python</div>

<p>
Also my box had Python 2.4 installed, I decided to install a fresh, 2.5
version of <a href="http://python.org/">Python</a>. You probably don't have to
repeat this step because Mercurial should work perfectly fine with Python 2.4.
</p>

<pre class="listing">
&gt; cd /share/software
&gt; tar -xzf Python-2.5.1.tgz
&gt; cd Python-2.5.1/
&gt; mkdir /share/software/Python-2.5.1_bin
&gt; configure --prefix=/share/software/Python-2.5.1_bin
&gt; make
&gt; make install
&gt; ln -s /share/software/Python-2.5.1_bin/bin/* /usr/local/bin/
</pre>

<p/>

<a name="Mercurial"> </a>
<div class="mh3">Mercurial</div>

<p>
After this step I downloaded, compiled and installed <a href="http://www.selenic.com/mercurial/">Mercurial</a>. As mentioned above,
you'll be probably fine if you use your default Python installation for this
step:
</p>

<pre class="listing">
&gt; cd /share/software
&gt; tar -xzf mercurial-0.9.5.tar.gz
&gt; cd mercurial-0.9.5/
&gt; make install-bin PYTHON=/share/software/Python-2.5.1_bin/bin/python PREFIX=/share/software/hg
&gt; ln -s /share/software/hg/lib/python2.5/site-packages/* /share/software/Python-2.5.1_bin/lib/python2.5/site-packages/
&gt; ln -s /share/software/hg/bin/hg/* /usr/local/bin/
&gt; cat &gt; ~/.hgrc
[ui]
username = Volker H. Simonis
^D
&gt; hg debuginstall
</pre>

<p>
The last command <span class="code">hg debuginstall</span>, should complete without error
and should produce the following output:
</p>

<pre class="listing">
Checking encoding (UTF-8)...
Checking extensions...
Checking templates...
Checking patch...
Checking merge helper...
Checking commit editor...
Checking username...
No problems detected
</pre>

<p/>

<a name="Forest"> </a>
<div class="mh3">The Forest Extension</div>

<p>
After I had a working Mercurial, I could use it to get the <a href="http://www.selenic.com/mercurial/wiki/index.cgi/ForestExtension">Forest
extension</a> which isn't strictly needed but which will simplify the download
of the OpenJDK sources. Note that you'll have to set the
<span class="code">http_proxy</span> environment variable to point to your http proxy
server if you're behind a firewall
(e.g. <span class="code">http_proxy=http://proxy:8080</span>).
</p>

<pre class="listing">
cd /share/software
hg clone http://www.terminus.org/hg/hgforest
ln -s /share/software/hgforest/forest.py /share/software/hg/lib/python2.5/site-packages/hgext/
</pre>

<p/>

<a name="Clone"> </a>
<div class="mh3">Cloning the OpenJDK sources</div>

<p>
Now comes the big moment. I fired up a <span class="code">hg fclone</span> command to clone
the OpenJDK sources. If everything works fine, this should download about 28.000
files to your local machine. The output should look as follows
(stripped-down..):
</p>

<pre class="listing">
&gt; cd /share/software
&gt; mkdir OpenJDK
&gt; cd OpenJDK
&gt; hg fclone http://hg.openjdk.java.net/jdk7/jdk7/ jdk7
[.]
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 26 changes to 26 files
26 files updated, 0 files merged, 0 files removed, 0 files unresolved

[corba]

... ... ...

[langtools]
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2974 changes to 2974 files
2974 files updated, 0 files merged, 0 files removed, 0 files unresolved
</pre>

<p>
There may still be a problem here, if you're behind a firewall. Instead of
getting the sources, you may get the following error:
</p>

<pre class="listing">
&gt; hg fclone http://hg.openjdk.java.net/jdk7/jdk7/ jdk7
[.]
abort: error: Name or service not known
</pre>

<p>
This is because of a <a href="http://mail.openjdk.java.net/pipermail/build-dev/2007-December/000628.html">bug
in fclone</a> which doesn't honor the setting of the <span class="code">http_proxy</span>
environment variable (although <span class="code">hg</span> alone does use
it). Fortunately, this can be fixed easily by setting the http proxy in the
<span class="file">~/.hgrc</span> configuration file like this:
</p>

<pre class="listing">
[http_proxy]
host=proxy:8080
</pre>

<p>
That's it! Now we should have the sources. In order to build them, we still
need to install some third party libraries like <a href="http://download.savannah.gnu.org/releases/freetype/">Freetype</a>, <a href="http://findbugs.sourceforge.net/index.html">Findbugs</a> and <a href="http://www.cups.org/">Cups</a> and of course the binary encumbrances
which are bundled in the appropriate <a href="http://download.java.net/openjdk/jdk7/">binary plugs file</a>. You may
skip any of the following installation steps if your Linux distribution already
has the development packages installed for the corresponding library.
</p>

<a name="Freetype"> </a>
<div class="mh3">Freetype</div>

<p>
Let's start with <a href="http://download.savannah.gnu.org/releases/freetype/">Freetype</a>:
</p>

<pre class="listing">
&gt; cd /share/software/OpenJDK
&gt; tar -xzf freetype-2.3.5.tar.gz
&gt; cd freetype-2.3.5/
&gt; vi include/freetype/config/ftoption.h
uncomment /* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
&gt; mkdir ../freetype-2.3.5_bin
&gt; ./configure --prefix=/share/software/OpenJDK/freetype-2.3.5_bin/
&gt; make
&gt; make install
</pre>

<p>
In order to make the Freetype library accessible for the OpenJDK build, we
can set the following environment variables:
</p>

<pre class="listing">
&gt; export ALT_FREETYPE_LIB_PATH=/share/software/OpenJDK/freetype-2.3.5_bin/lib
&gt; export ALT_FREETYPE_HEADERS_PATH=/share/software/OpenJDK/freetype-2.3.5_bin/include
</pre>

<p>
Another possibility to make a library available during the OpenJDK build is to
set the corresponding variable on the make command line. This is the
approach that I'll use later on in the <a href="#Build">build
section</a>. Nevertheless, I'll also list the export statements after the
installation of each library for the sake of completeness.
</p>

<a name="Findbugs"> </a>
<div class="mh3">Findbugs</div>

<p>
The same thing for <a href="http://findbugs.sourceforge.net/index.html">Findbugs</a> ..
</p>

<pre class="listing">
&gt; cd /share/software/OpenJDK
&gt; tar -xzf findbugs-1.3.1.tar.gz
&gt; export FINDBUGS_HOME=/share/software/OpenJDK/findbugs-1.3.1
</pre>

<p/>

<a name="Cups"> </a>
<div class="mh3">Cups</div>

<p>
.. and <a href="http://www.cups.org/">Cups</a>:
</p>

<pre class="listing">
&gt; cd /share/software/OpenJDK
&gt; tar -xzf cups-1.3.5-source.tar.gz
&gt; cd cups-1.3.5/
&gt; mkdir ../cups-1.3.5_bin
&gt; ./configure --prefix=/share/software/OpenJDK/cups-1.3.5_bin 
&gt; make
&gt; make install
&gt; export ALT_CUPS_HEADERS_PATH=/share/software/OpenJDK/cups-1.3.5_bin/include
</pre>

<p/>

<a name="Binaryplugs"> </a>
<div class="mh3">Binary plugs, Boot JDK and Ant</div>

<p>
Finally we need to get the <a href="http://download.java.net/openjdk/jdk7/">Binary plugs</a> and a boot JDK
(at least Java 6). I already had Java 6 and Ant installed in
<span class="file">/share/software/Java/1.6.0</span> and
<span class="file">/share/software/Ant/1.6.4</span> respectively, so I only had to download
and install the Binary plugs and make all of them known to the OpenJDK build:
</p>

<pre class="listing">
&gt; cd /share/software/OpenJDK
&gt; java -jar jdk-7-ea-plug-b24-linux-i586-04_dec_2007.jar
&gt; export ALT_BINARY_PLUGS_PATH=/share/software/OpenJDK/jdk-7-ea-plug-b24-linux-i586-04_dec_2007/openjdk-binary-plugs
&gt; export ALT_BOOTDIR=/share/software/Java/1.6.0
&gt; export ANT_HOME=/share/software/Ant/1.6.4/
</pre>

<p>
With this step we ultimately finished the necessary preparations and can now
happily proceed to build the OpenJDK!
</p>

<a name="Build"> </a>
<div class="mh2">Building the OpenJDK</div>

<p>
Before we start the build, we should first run the sanity check to see if our
settings and the available tools and libraries are sufficient for the
build. Because I don't like to clutter my environment, I'll set all the needed
environment variables on the command line, such that they only affect the
current command as follows:
</p>

<pre class="listing">
&gt; cd /share/software/OpenJDK/jdk7
&gt; LANG=C \
  FINDBUGS_HOME=/share/software/OpenJDK/findbugs-1.3.1 \
  ANT_HOME=/share/software/Ant/1.6.4/ \
  ALT_CUPS_HEADERS_PATH=/share/software/OpenJDK/cups-1.3.5_bin/include \
  ALT_BOOTDIR=/share/software/Java/1.6.0 \
  ALT_BINARY_PLUGS_PATH=/share/software/OpenJDK/jdk-7-ea-plug-b24-linux-i586-04_dec_2007/openjdk-binary-plugs \
  ALT_FREETYPE_LIB_PATH=/share/software/OpenJDK/freetype-2.3.5_bin/lib \
  ALT_FREETYPE_HEADERS_PATH=/share/software/OpenJDK/freetype-2.3.5_bin/include \
  make sanity
</pre>

<p>
You shouldn't proceed forward, until the sanity check completes without any
errors or warnings. The checks performed by the sanity check are still quite
weak and a passed sanity check is no guarantee for a successful build. The
sanity check for example just verifies that ALT_BINARY_PLUGS_PATH points to a
valid directory, but not if that directory really contains the binary plugins!
</p>

<a name="WARNINGS_ARE_ERRORS"> </a>
<p>
Internally, SUN apparently still uses gcc 3.2.2 to build the JDK and with gcc
3.2.2 there seem to be no warnings during the build so they decided to use the
<span class="code">-Werror</span> option on Linux which instructs gcc to treat every
compiler warning as error. If you however want to build with a gcc version
higher than 3.2.2 (and you'll probably want to do this on a newer Linux
distribution) you'll either have to use precompiled headers
(<span class="code">USE_PRECOMPILED_HEADER=true</span>) or comment the line
<span class="code">WARNINGS_ARE_ERRORS = -Werror</span> in the file
<a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/build/linux/makefiles/gcc.make" class="jdkfile">hotspot/build/linux/makefiles/gcc.make</a> (see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6469784">Bug
6469784</a>).
</p>

<p>
Using precompiled headers is probably the easier way to go for first time
users and it has the additional benefit of speeding up the build
considerably. But it only helps with warnings related to inlining and it has
the disadvantage of hiding problems with the includeDB (see <a href="http://comments.gmane.org/gmane.comp.java.openjdk.hotspot.devel/157">this
mail thread</a> for a discussion of the topic). If you want to use gcc 4.3 or
higher, you'll probably have to disable the treatment of warnings as errors
for a successful build (see for example <a href="http://permalink.gmane.org/gmane.comp.java.openjdk.distro-packaging.devel/512">here</a>).
</p>

<p>
Building the corba subdirectory will fail if you haven't set
<span class="code">ALT_JDK_IMPORT_PATH</span>. This is because of a known bug in
<a href="http://hg.openjdk.java.net/jdk7/jdk7//corba/raw-file/jdk7-b24/make/common/shared/Defs.gmk" class="jdkfile">corba/make/common/shared/Defs.gmk</a> (see <a href="http://www.mail-archive.com/build-dev@openjdk.java.net/msg00275.html">
this mail thread</a>). You can fix the problem by inserting the following
lines into <a href="http://hg.openjdk.java.net/jdk7/jdk7//corba/raw-file/jdk7-b24/make/common/shared/Defs.gmk" class="jdkfile">corba/make/common/shared/Defs.gmk</a>, just before the
line that includes <span class="file">Compiler.gmk</span>:
</p>

<div class="listing cpp"><pre class="listing">
ifdef ALT_LANGTOOLS_DIST
  LANGTOOLS_DIST :=$(call FullPath,$(ALT_LANGTOOLS_DIST))
else
  LANGTOOLS_DIST =
endif
</pre></div>

<p>
After this last patch, we can finally start the build. I'll focus here on
debug builds because you're probably a developer if you read this and as a
developer you're probably interested in a debug build (after all you could
download a product build, so it would not be worth the work).
</p>

<pre class="listing">
&gt; cd /share/software/OpenJDK/jdk7
&gt; LANG=C \
  FINDBUGS_HOME=/share/software/OpenJDK/findbugs-1.3.1 \
  ANT_HOME=/share/software/Ant/1.6.4/ \
  ALT_CUPS_HEADERS_PATH=/share/software/OpenJDK/cups-1.3.5_bin/include \
  ALT_BOOTDIR=/share/software/Java/1.6.0/ \
  ALT_BINARY_PLUGS_PATH=/share/software/OpenJDK/jdk-7-ea-plug-b24-linux-i586-04_dec_2007/openjdk-binary-plugs \
  ALT_FREETYPE_LIB_PATH=/share/software/OpenJDK/freetype-2.3.5_bin/lib \
  ALT_FREETYPE_HEADERS_PATH=/share/software/OpenJDK/freetype-2.3.5_bin/include \
  HOTSPOT_BUILD_JOBS=5 \
  ALT_PARALLEL_COMPILE_JOBS=5 \
  USE_PRECOMPILED_HEADER=true \
  SKIP_DEBUG_BUILD=false \
  SKIP_FASTDEBUG_BUILD=true \
  DEBUG_NAME=debug \
  ALT_OUTPUTDIR=/share/software/OpenJDK/jdk7/build/openjdk_full_debug \
  make 2&gt;&amp;1 | tee /share/software/OpenJDK/jdk7/build/openjdk_full_debug.log
</pre>

<p>
Note that we don't use the <span class="code">make_debug</span> target because there's a
bug in the top-level Makefile that ignores the <span class="code">ALT_OUTPUTDIR</span> if
that target will be used (see <a href="http://mail.openjdk.java.net/pipermail/build-dev/2008-January/000669.html">this
mail thread</a>). You should be also aware of the fact, that the build will
always create an empty directory named
<span class="file">&lt;ALT_OUTPUTDIR&gt;-fastdebug</span> which can be ignored and removed.
</p>

<p>
It is also advisable to save the build output in a file. This can be achieved
by redirecting the whole output to <span class="code">tee</span> as shown in the call to
<span class="code">make</span> above. <span class="code">tee</span> is a utility that duplicates its
input to the standard output and to an additional file. This file can be
consulted later on if there have been build problems or if we just want to know
how a file has been built and where the resulting object files have been
placed to.
</p>

<p>
Following the above pattern it is also possible to build a product or a
fastdebug build. You just have to set <span class="code">SKIP_DEBUG_BUILD=true
SKIP_FASTDEBUG_BUILD=false DEBUG_NAME=fastdebug</span> for a fastdebug build
and <span class="code">SKIP_DEBUG_BUILD=true SKIP_FASTDEBUG_BUILD=true</span> for a product
build.
</p>

<p>
Notice that <span class="code">ALT_PARALLEL_COMPILE_JOBS</span> is currently only honored
by the corba and the jdk subprojects while the hotspot subproject uses
<span class="code">HOTSPOT_BUILD_JOBS</span> as indicator to do a parallel
build. Unfortunately, due to <a href="http://mail.openjdk.java.net/pipermail/build-dev/2008-January/000673.html">another
bug</a>, neither <span class="code">ALT_PARALLEL_COMPILE_JOBS</span> nor
<span class="code">HOTSPOT_BUILD_JOBS</span> is handed over from the top-level makefile to
the hotspot makefile. However, this can be easily fixed by adding the following
lines to <a href="http://hg.openjdk.java.net/jdk7/jdk7///raw-file/jdk7-b24/make/hotspot-rules.gmk" class="jdkfile">/make/hotspot-rules.gmk</a>, just before the
<span class="code">hotspot-build</span> target:
</p>

<pre class="listing">
ifneq ($(PARALLEL_COMPILE_JOBS), 1)
  HOTSPOT_BUILD_ARGUMENTS += HOTSPOT_BUILD_JOBS=$(PARALLEL_COMPILE_JOBS)
endif
</pre>

<p>
With this change, setting <span class="code">ALT_PARALLEL_COMPILE_JOBS</span> on the make
command line will be enough to trigger a parallel hotspot build, which should
be considerable faster on a multi-processor machine (a good default setting
for <span class="code">ALT_PARALLEL_COMPILE_JOBS</span> is hard to predict, but 1.5xNrOfCPUs
should be a good starting point).
</p>

<p>
Sooner or later (depending on your machine and the right setting of
<span class="code">ALT_PARALLEL_COMPILE_JOBS</span>:) the build should finish (hopefully
without any error). Among others, this will create the following
subdirectories in the build location that was specified with
<span class="code">ALT_OUTPUTDIR</span>:
</p>

<pre class="listing">
bin
corba
j2sdk-image
lib
hotspot
include
j2re-image
langtools
</pre>

<p>
<span class="code">corba</span>, <span class="code">hotspot</span> and <span class="code">langtools</span> contains
the build results of the corresponding subprojects. <span class="code">bin</span>,
<span class="code">include</span> and <span class="code">lib</span> contain the binaries, include files
and libraries that are contained in the corresponding directories of a Java
SDK or RE distribution. Finally, <span class="code">j2sdk-image</span> and
<span class="code">j2re-image</span> contain a complete image of a Java SDK or RE
distribution, assembled from the subdirectories of the build subdirectory. If
everything went fine, we can now call <span class="file">bin/java</span> (or
<span class="file">j2sdk-image/bin/java</span> or <span class="file">j2re-image/bin/java</span> which is
all the same) to verify our build:
</p>

<pre class="listing">
&gt; /share/software/OpenJDK/jdk7/build/openjdk_full_debug/bin/java -version
openjdk version "1.7.0-internal-debug"
OpenJDK Runtime Environment (build 1.7.0-internal-debug-dXXXXXX_04_jan_2008_11_27-b00)
OpenJDK Server VM (build 12.0-b01-jvmg, mixed mode)
</pre>

<p>
That looks really nice, isn't it!!! We managed to built a complete debug
version of the OpenJDK from scratch!
</p>

<a name="HotSpotBuild"> </a>
<div class="mh3">Building the HotSpot</div>

<p>
Now that we've successfully built the OpenJDK and started hacking the HotSpot
VM, we probably don't want to go through all this hassle just to verify that a
small VM change compiles and works correctly. Luckily, the HotSpot developers
at SUN didn't wanted either, so they provided an elegant way to rebuild the
HotSpot part of the VM and test it.
</p>

<p>
And here is how it works. Go to the <span class="file">hotspot/make</span> directory and
execute the following make command:
</p>

<pre class="listing">
&gt; LANG=C \
  ALT_BOOTDIR=/share/software/Java/1.6.0/ \
  HOTSPOT_BUILD_JOBS=5 \
  ALT_OUTPUTDIR=../../build/hotspot_debug \
  make jvmg jvmg1 2&gt;&amp;1 | tee ../../build/hotspot_debug.log
</pre>

<p>
As you can see, there are considerably fewer variables needed to build the VM
(in fact the only real dependency is the boot JDK specified with
<span class="code">ALT_BOOTDIR</span>). By selecting the corresponding build target it is
possible to build debug builds (<span class="code">jvmg</span> and <span class="code">jvmg1</span>
targets), fastdebug builds (<span class="code">fastdebug</span> and
<span class="code">fastdebug1</span> targets), optimized builds (<span class="code">optimized</span>
and <span class="code">optimized1</span> targets) and product builds (<span class="code">product</span>
and <span class="code">product1</span> targets). A "<span class="code">1</span>"-suffix in the target
name indicates that the client version (the one with the C1 JIT compiler) will
be build while a target name without suffix will build the server version (the
one with the C2 JIT compiler) of the corresponding VM. A fastdebug build is an
optimized build with assertions (C/C++ style asserts in the VM code)
enabled. An optimized build has no assertions, while a product build is an
optimized build without assertions and <span class="code">-DPRODUCT</span> defined (this may
for example disable non-product switches in the resulting VM).
</p>

<p>
With this information in mind, you'll probably easily guess that the last
<span class="code">make</span> command builds the debug version of the client and the
server VM. The results will be placed in the corresponding
<span class="file">&lt;os&gt;_&lt;arch&gt;_compiler1/</span> and
<span class="file">&lt;os&gt;_&lt;arch&gt;_compiler2/</span> subdirectories of the output
directory with the little anomaly that debug build will be placed in the
<span class="file">jvmg</span> subdirectory (i.e. <span class="file">linux_i486_compiler1/jvmg/</span>
and <span class="file">linux_i486_compiler2/jvmg/</span> in this example).
</p>

<a name="HotSpotRun"> </a>
<div class="mh3">Running the HotSpot</div>

<p>
These directories not only contain the HotSpot VM as a shared library
(<span class="file">libjvm.so</span>) but also a small executable called
<span class="file">gamma</span>. I don't really know the origin of this name (perhaps
someone of the geeks can comment on this?), but it is a really convenient
possibility to test the newly created VM:
</p>

<pre class="listing">
&gt; build/hotspot_debug/linux_i486_compiler1/jvmg/gamma -version
build/hotspot_debug/linux_i486_compiler1/jvmg/gamma: \
 error while loading shared libraries: libjvm.so: \
 cannot open shared object file: No such file or directory

&gt; LD_LIBRARY_PATH=build/hotspot_debug/linux_i486_compiler1/jvmg \
  build/hotspot_debug/linux_i486_compiler1/jvmg/gamma -version
JAVA_HOME must point to a valid JDK/JRE to run gamma
Error: could not find libjava.so
Error: could not find Java 2 Runtime Environment.

&gt; LD_LIBRARY_PATH=build/hotspot_debug/linux_i486_compiler1/jvmg \
  JAVA_HOME=build/openjdk_full_debug/j2sdk-image \
  build/hotspot_debug/linux_i486_compiler1/jvmg/gamma -version
openjdk version "1.7.0-internal-debug"
OpenJDK Runtime Environment (build 1.7.0-internal-debug-dXXXXXX_04_jan_2008_11_27-b00)
OpenJDK Client VM (build 12.0-b01-internal-jvmg, mixed mode)
</pre>

<p>
As you can see, we just have to put the directory which contains the desired
<span class="file">libjvm.so</span> (client or server) into the
<span class="code">LD_LIBRARY_PATH</span> and define <span class="code">JAVA_HOME</span> to point to a
valid JDK or JRE (e.g. the one we built in the <a href="#Build">first
step</a>). <span class="code">gamma</span> is a simple launcher intended for internal
engineering test. It is build from
<a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/src/os/linux/launcher/java.c" class="jdkfile">hotspot/src/os/linux/launcher/java.c</a> and
<a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/src/os/linux/launcher/java_md.c" class="jdkfile">hotspot/src/os/linux/launcher/java_md.c</a> (search for
<span class="file">launcher.c</span> in the build log to see the
details). <a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/src/os/linux/launcher/java.c" class="jdkfile">hotspot/src/os/linux/launcher/java.c</a> and
<a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/src/os/linux/launcher/java_md.c" class="jdkfile">hotspot/src/os/linux/launcher/java_md.c</a> are stripped down
versions of the real Java launcher sources
<a href="http://hg.openjdk.java.net/jdk7/jdk7//jdk/raw-file/jdk7-b24/src/share/bin/java.c" class="jdkfile">jdk/src/share/bin/java.c</a> and
<a href="http://hg.openjdk.java.net/jdk7/jdk7//jdk/raw-file/jdk7-b24/src/solaris/bin/java_md.c" class="jdkfile">jdk/src/solaris/bin/java_md.c</a> from the <span class="file">jdk</span>
workspace. The <span class="code">gamma</span> launcher misses some of the logic of the
default Java launcher which finds the corresponding VM and JDK
automatically. Therefore it is necessary to signal their location by setting
the <span class="code">LD_LIBRAY_PATH</span> and <span class="code">JAVA_HOME</span> environment
variables. The big advantage however is the fact that it builds within the hotspot
project without any dependency on the <span class="code">jdk</span> workspace and comes in
quite handy for fast development and testing.
</p>

<p>
Just as a side note: you probably wondered why I wrote
<a href="http://hg.openjdk.java.net/jdk7/jdk7//jdk/raw-file/jdk7-b24/src/solaris/bin/java_md.c" class="jdkfile">jdk/src/solaris/bin/java_md.c</a> in the previous paragraph,
for the location of <span class="file">java_md.c</span> in the <span class="file">jdk</span>
workspace. The <span class="file">solaris</span> part was not a typo. The <span class="file">jdk</span>
workspace isn't that well structured like the <span class="file">hotspot</span> workspace
which divides platform and architecture dependant files into the corresponding
<span class="file">os</span>, <span class="file">cpu</span> and <span class="file">os_cpu</span>
subdirectories. Instead, in the <span class="file">jdk</span> workspace there's just a
<span class="file">windows</span> directory for the Windows native code and a
<span class="file">solaris</span> directory which contains all the Unix native code
(separated by <span class="code">ifdef</span>s if necessary). (In fact there is a
<span class="file">linux</span> subdirectory, but it only contains the linux man pages and
no code). This may identify as serious problem for the various <a href="http://openjdk.java.net/groups/porters/">porting projects</a> which
attempt to port the OpenJDK to other Unix-like operation systems.
</p>

<p>
Currently, the <span class="code">gamma</span> launcher is somewhat outdated
(<a href="http://hg.openjdk.java.net/jdk7/jdk7//hotspot/raw-file/jdk7-b24/src/os/linux/launcher/java.c" class="jdkfile">hotspot/src/os/linux/launcher/java.c</a> is based on the
1.6.0-b28 JDK version of <a href="http://hg.openjdk.java.net/jdk7/jdk7//jdk/raw-file/jdk7-b24/src/share/bin/java.c" class="jdkfile">jdk/src/share/bin/java.c</a> as stated
in the file) but it is still sufficient to test the HotSpot VM. Hopefully it
will be updated, as the JDK7 development moves forward.
</p>



<a name="CC_INTERP_Build"> </a>
<div class="mh3">Building a HotSpot with C++-Interpreter</div>

<p>
If you want to build the C++-Interpreter instead of the default template
interpreter, you have to additionally set <span class="code">CC_INTERP=true</span> on the
build command line. Currently the C++-Interpreter only works for the 32-bit
x86 debug build and for the 32-bit opt and debug builds on SPARC (see my <a href="http://weblogs.java.net/blog/simonis/archive/2007/11/template_vs_cin.html">previous
blog entry</a> for how to get the 32-bit x86 opt and the 64-bit SPARC
versions running). Notice that you'll also have to disable the <a href="#WARNINGS_ARE_ERRORS">the treatment of warnings as errors</a> if you
built the C++-Interpreter, because its sources generate some warnings.
</p>

<p>
<a name="Linux_Patch"> </a>
For your convenience I created a <a href="http://weblogs.java.net/blog/simonis/patch/linux32.patch/linux32.patch">patch
file</a> (in fact I run <span class="code">hg diff &gt; linux32.pach</span> in the
<span class="file">hotspot</span> directory) which fixes all the problems mentioned so
far. To apply it, just download it and call <span class="code">patch</span> as follows:
</p>

<pre class="listing">
&gt; cd hotspot/
&gt; patch -p1 &lt; linux32.patch
patching file build/linux/makefiles/gcc.make
patching file src/cpu/x86/vm/cppInterpreter_x86.cpp
patching file src/share/vm/interpreter/bytecodeInterpreter.cpp
</pre>

<p>
You should now be able to build a debug version of the C++-Interpreter enabled
HotSpot with the following command:
</p>

<pre class="listing">
&gt; LANG=C \
  ALT_BOOTDIR=/share/software/Java/1.6.0/ \
  HOTSPOT_BUILD_JOBS=5 \
  ALT_OUTPUTDIR=../../build/hotspot_CC_INTERP_debug \
  CC_INTERP=true \
  make jvmg jvmg1 2&gt;&amp;1 | tee ../../build/hotspot_CC_INTERP_debug.log
</pre>



<p>
Notice that building an interpreter-only VM isn't currently supported out of the
box with the current top-level HotSpot makefiles. Previously, the CORE targets
(<span class="code">debugcore</span>, <span class="code">jvmgcore</span>, <span class="code">fastdebugcore</span>,
<span class="code">optimizedcore</span>, <span class="code">profiledcore</span> and
<span class="code">productcore</span>) could be used for this purpose and building the
HotSpot that way, gave you a pure, interpreter-only VM. However now, as Tom
Rodriguez <a href="http://permalink.gmane.org/gmane.comp.java.openjdk.hotspot.devel/429?set_blog_all=yes">explains</a>
"..core is just a system without a compiler but still including the classes
needed by the compiler like nmethod so it's slightly less minimal ... and the
core makefile targets should still work". These core targets are defined in
the platform-dependant makefiles
<span class="file">hotspot/build/&lt;os&gt;/Makefile</span> only, and not in
<span class="file">hotspot/make/Makefile</span> so you'll probably have to hack
<span class="file">hotspot/make/Makefile</span> to build them.
</p>

<a name="NetBeans"> </a>
<div class="mh2">Developing with NetBeans</div>

<p>
See <a href="http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html">HotSpot development on Linux with NetBeans - Part 2</a>
</p>

<p/>

<a name="References"> </a>
<div class="mh2">References</div>

<p>

[1] <a href="http://weblogs.java.net/blog/kellyohair/archive/2006/12/jdk6_build_chea.html">Kelly
O'Hair's Build Cheat Sheet</a>
<br/>

[2] <a href="http://blogs.sun.com/kto/entry/glossary_for_jdk_builds">Kelly
O'Hair's Glossary for JDK Builds</a>
<br/>

[3] <a href="http://hg.openjdk.java.net/jdk7/jdk7/raw-file/jdk7-b24/README-builds.html">OpenJDK
Build Readme</a>
<br/>

[4] <a href="http://www.netbeans.org/kb/60/cnd/quick-start.html">NetBeans
C/C++ Support Quick Start Tutorial</a>
<br/>


[5] <a href="http://blogs.sun.com/SDNChannel/entry/the_new_face_of_sun">Interview
with Gordon Prieur about Sun Studio 12
</a>
<br/>

</p>

</body>
</html>]]>

</content>
</entry>
<entry>
<title>Template- vs. C++-Interpreter shootout</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/simonis/archive/2007/11/template_vs_cin_1.html" />
<modified>2008-06-24T19:17:03Z</modified>
<issued>2007-11-16T11:22:13Z</issued>
<id>tag:weblogs.java.net,2007:/blog/simonis/427.8665</id>
<created>2007-11-16T11:22:13Z</created>
<summary type="text/plain">This blog discusses the main differences between the C++ and the Template Interpreter which are both available within the Hotspot sources of the OpenJDK project. Some performance tests with the DaCapo benchmark suite which compare the two interpreters in mixed and interpreted mode on Linux/x86 and Solaris/SPARC conclude the presentation.</summary>
<author>
<name>simonis</name>

<email>volker.simonis@gmail.com</email>
</author>
<dc:subject>Virtual Machine</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/simonis/">
<![CDATA[<html>

<head>

<style type="text/css" id="internalStyle">
  body {
    font-family: arial, helvetica, sans-serif;
    font-size: 10pt;
  }

  table.my {
    font-family: arial, helvetica, sans-serif;
    font-size: 10pt;
    background-color: #d3d3d3;#lightgray;
    border-style: solid;
    border-width: 1px;
    border-color: black;
    border-collapse: collapse;
    margin: 8px 0px 5px 0px;
    padding: 2px;
    width: auto; 
    overflow: auto;
  }

  td.my {
    border-width: 1px;
    border-style: solid;
    padding: 2px;
    font-family: monospace;
    background-color: white;
    border-color: black;
  }

  td.highlight {
    border-width: 1px;
    border-style: solid;
    padding: 2px;
    font-family: monospace;
    background-color: #e8e8ff;
    border-color: black;
  }

  th.my {
    border-width: 1px;
    border-style: solid;
    padding: 2px;
    font-size: 9pt;
    font-weight: bold;
    border-color: black;
  }

  tr.footer {
    background-color: #ffffe0;
    border-color: black;
    border-width: 1px;
    border-style: solid;
  }
  th.footer {
    background-color: #ffffe0;
    border-color: black;
  }
  td.footer {
    font-family: arial, helvetica, sans-serif;
    font-size: 9pt;
    background-color: #ffffe0;
    border-color: black;
    border-width: 1px;
    border-style: solid;
  }

  pre.listing {
    display: table;
    color: black;
    background-color: lightgray;
    border-style: solid;
    border-width: 1px;
    border-color: darkgray;
    margin: 8px 0px 5px 0px;
    padding: 2px;
    width: auto; 
    overflow: auto;  
    font-family: monospace;
  }

  .warning {
    color: red;
    font-size:  0.8em;
    text-align: center;
  }

  .mh1 {
    color: #202080;
    font-size:  1.2em;
    font-weight: bold;
  }

  .mh2 {
    color: #202080;
    font-size:  1em;
    font-weight: bold;
  }

  .mh3 {
    color: #404040;
    font-size:  1em;
    font-weight: bold;
  }

  .system {
    font-family: monospace;
  }

  .file {
    font-family: monospace;
  }

  .jdkfile {
    font-family: monospace;
  }

  .code {
    font-family: monospace;
  }

  a {
    text-decoration: none;
  }
</style>

<title>Template- vs. C++-Interpreter shootout</title>

</head>

<body>

<div class="mh2">The Template-Interpreter</div>

<p>
The default interpreter that comes with the Hotspot VM is the so called
"Template Interpreter". It is called template interpreter, because it is
basically created at runtime (every time the Hotspot starts) from a kind of
assembler templates which are translated into real machine code. Notice, that
although this is code generation at runtime it should not be confused with the
ability of the Hotspot to do Just In Time (JIT) compilation of computationally
expensive program parts.
</p>

<p>
While a JIT compiler compiles a whole method (or even more methods together if
we consider inlining) into executable machine code, the template interpreter,
although generated at runtime, is still just an interpreter. It interprets a
Java program bytecode by bytecode. The advantage of the template interpreter
approach is the fact hat most of the code that gets executed for every single
bytecode is pure machine code as well as the dispatching from one bytecode to
the next, which can also be done in native machine code. Moreover this
technique allows a very tight adaption of the interpreter to the actual
processor architecture so the same binary will still run on an old 80486 while
it may well use the latest and greatest features of the newest processor
generation if available.
</p>

<p>
Beside the slightly increased startup time, the second drawback of the
template interpreter approach is the fact that the interpreter itself is quite
complicated. It requires for example a kind of builtin runtime assembler,
which translates the code templates into machine code. Therfore porting the
template interpreter to a new processor architecture is not an easy task and
requires quite a profound knowledge of the underlying architecture.
</p>

<div class="mh2">The C++-Interpreter</div>

<p>
In the earlier Java days (around JDK 1.4) a second interpreter existed beside
the template interpreter - the so called C++ Interpreter. It was probably
named that way, because the main interpreter loop was implemented as a huge
switch statement in C++. Despite its name however, even the C++ Interpreter
isn't completely implemented in C++. It still contains large parts like for
example the frame manager which are written in assembler. It doesn't rely on
recursive C++ method invocations to realize function calls in Java but instead
uses the frame manager just mentioned before, which controls the stack
manually. But despite these issues, the C++ interpreter is probably still
easier to port to a new architecture than the template interpreter.
</p>

<p>
In Java 1.4 the C++ interpreter has been used for the Itanium port of the
Hotspot. But after SUN abandoned the support for the Itanium architecture, it
got quite silent around the C++ Interpreter although it was still present in
the Hotspot sources. With the advent of OpenJDK, the demand from the developer
community to get a working example of the C++ interpreter grew (see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6571248">BugID:
6571248</a>) and so the C++ interpreter was finally reactivated in build 20 of
OpenJDK, (at least for the i486 and the SPARC architecture).
</p>

<p>
The C++ interpreter was basically working out of the box for the 32-bit x86
debug build and for the 32-bit opt and debug build on SPARC. If you would like
to try the opt build on a 32-bit x86 platform, you'll currently have to apply
this small patch: <a href="http://weblogs.java.net/blog/simonis/patch/bytecodeInterpreter.patch">bytecodeInterpreter.patch</a>. To make the C++
interpreter 64-bit clean on SPARC, a few more changes have to made, but I
succeeded to get it running (at least for the <a href="http://www.spec.org/osg/jvm98/">JVM98</a> and the <a href="http://dacapobench.org/">DaCapo</a> benchmark suits) by applying these
patches: <a href="http://weblogs.java.net/blog/simonis/archive/bytecodeInterpreter_sparc.hpp.patch">bytecodeInterpreter_sparc.hpp.patch</a>, <a href="http://weblogs.java.net/blog/simonis/patch/cppInterpreter_sparc.cpp.patch">cppInterpreter_sparc.cpp.patch</a>, <a href="http://weblogs.java.net/blog/simonis/patch/parseHelper.cpp.patch">parseHelper.cpp.patch</a>. After applying the patches you can build
the Hotspot VM with the C++ interpreter instead of the usual template
interpreter by setting the environment variable <span class="code">CC_INTERP</span> in the
shell where the build is started.
</p>

<div class="mh2">Template- vs. C++-Interpreter shootout</div>

<p>
Beside the expected porting effort, performance will be probably one of the
other main reasons for the decision for or against one of the two
interpreters. I have therfore run the <a href="http://dacapobench.org/">DaCapo</a> performance test suite with both
interpreters in interpreter only mode (<a href="http://weblogs.java.net/blog/simonis/archive/2007/08/topsecret_xinte_1.html"><span class="code">-Xint</span></a>)
and in mixed mode (<a href="http://weblogs.java.net/blog/simonis/archive/2007/08/topsecret_xinte_1.html"><span class="code">-Xmixed</span></a>)
together with the C2 server JIT compiler. The tests have been executed with a
32-bit VM on Linux/x86 and with a 32- and a 64-bit VM on Solaris/SPARC. The
results can be seen in the following tables.
</p>

<table class="my">
<caption><div class="mh3">Table 1: Interpreted execution (-Xint) on Solaris/Sparc</div></caption>
<tr><th class='my'/><th class='my' colspan="3"> 32 bit </th><th class='my' colspan="3"> 64 bit </th></tr>
<tr><th class='my'/><th class='my'> Template <br/> Interpreter </th><th class='my'> C++ <br/> Interpreter </th><th class='my'><span style="text-decoration:underline"> (Tmpl*100)</span><br/>C++ </th><th class='my'> Template <br/> Interpreter </th><th class='my'> C++ <br/> Interpreter </th><th class='my'><span style="text-decoration:underline"> (Tmpl*100)</span><br/>C++ </th></tr>
<tr><th class='my' align="left"> antlr </th><td class='my' align="right"> 126516 ms</td><td class='my' align="right"> 257359 ms</td><td class="highlight" align="center"> 49.16% </td><td class='my' align="right"> 131355 ms</td><td class='my' align="right"> 289253 ms</td><td class="highlight" align="center"> 45.41% </td></tr>
<tr><th class='my' align="left"> bloat </th><td class='my' align="right"> 327444 ms</td><td class='my' align="right"> 851316 ms</td><td class="highlight" align="center"> 38.46% </td><td class='my' align="right"> 352711 ms</td><td class='my' align="right"> 956596 ms</td><td class="highlight" align="center"> 36.87% </td></tr>
<tr><th class='my' align="left"> chart </th><td class='my' align="right"> 250255 ms</td><td class='my' align="right"> 600670 ms</td><td class="highlight" align="center"> 41.66% </td><td class='my' align="right"> 265860 ms</td><td class='my' align="right"> 677299 ms</td><td class="highlight" align="center"> 39.25% </td></tr>
<tr><th class='my' align="left"> eclipse </th><td class='my' align="right"> 1003766 ms</td><td class='my' align="right"> 2180171 ms</td><td class="highlight" align="center"> 46.04% </td><td class='my' align="right"> 1041304 ms</td><td class='my' align="right"> 2454685 ms</td><td class="highlight" align="center"> 42.42% </td></tr>
<tr><th class='my' align="left"> fop </th><td class='my' align="right"> 19114 ms</td><td class='my' align="right"> 44072 ms</td><td class="highlight" align="center"> 43.37% </td><td class='my' align="right"> 20614 ms</td><td class='my' align="right"> 49592 ms</td><td class="highlight" align="center"> 41.57% </td></tr>
<tr><th class='my' align="left"> hsqldb </th><td class='my' align="right"> 67514 ms</td><td class='my' align="right"> 159739 ms</td><td class="highlight" align="center"> 42.27% </td><td class='my' align="right"> 76838 ms</td><td class='my' align="right"> 186426 ms</td><td class="highlight" align="center"> 41.22% </td></tr>
<tr><th class='my' align="left"> jython </th><td class='my' align="right"> 184255 ms</td><td class='my' align="right"> 445747 ms</td><td class="highlight" align="center"> 41.34% </td><td class='my' align="right"> 197455 ms</td><td class='my' align="right"> 504520 ms</td><td class="highlight" align="center"> 39.14% </td></tr>
<tr><th class='my' align="left"> luindex </th><td class='my' align="right"> 317580 ms</td><td class='my' align="right"> 726604 ms</td><td class="highlight" align="center"> 43.71% </td><td class='my' align="right"> 325140 ms</td><td class='my' align="right"> 809468 ms</td><td class="highlight" align="center"> 40.17% </td></tr>
<tr><th class='my' align="left"> lusearch </th><td class='my' align="right"> 57484 ms</td><td class='my' align="right"> 139343 ms</td><td class="highlight" align="center"> 41.25% </td><td class='my' align="right"> 61858 ms</td><td class='my' align="right"> 158497 ms</td><td class="highlight" align="center"> 39.03% </td></tr>
<tr><th class='my' align="left"> pmd </th><td class='my' align="right"> 153715 ms</td><td class='my' align="right"> 376361 ms</td><td class="highlight" align="center"> 40.84% </td><td class='my' align="right"> 164771 ms</td><td class='my' align="right"> 430127 ms</td><td class="highlight" align="center"> 38.31% </td></tr>
<tr><th class='my' align="left"> xalan </th><td class='my' align="right"> 69368 ms</td><td class='my' align="right"> 171061 ms</td><td class="highlight" align="center"> 40.55% </td><td class='my' align="right"> 75989 ms</td><td class='my' align="right"> 196171 ms</td><td class="highlight" align="center"> 38.74% </td></tr>
<tr class="footer"><th class='my' class="footer" align="left">CmdLine</th><td class="footer" colspan="6">java [-d64 | -d32] -Xint -server
-Xms256m -Xmx256m -jar dacapo-2006-10-MR2.jar\<br/>-s default -n 7
antlr bloat chart eclipse fop hsqldb jython lusearch luindex pmd
xalan<br/><b>Best out of 3 runs</b> (only interpreter - no need to warmup)</td></tr>
<tr class="footer"><th class='my' class="footer" align="left">System</th><td class="footer" colspan="6">SunOS 5.10, Sun-Fire-V440, 16GB memory, 4
UltraSPARC-IIIi CPUs at 1281 MHz</td></tr>
</table>

<p/>

<table class="my">
<caption><div class="mh3">Table 2: Mixed mode execution (-Xmixed) on Solaris/Sparc</div></caption>
<tr><th class='my'/><th class='my' colspan="3"> 32 bit </th><th class='my' colspan="3"> 64 bit </th></tr>
<tr><th class='my'/><th class='my'> Template <br/> Interpreter </th><th class='my'> C++ <br/> Interpreter </th><th class='my'><span style="text-decoration:underline"> (Tmpl*100)</span><br/>C++ </th><th class='my'> Template <br/> Interpreter </th><th class='my'> C++ <br/> Interpreter </th><th class='my'><span style="text-decoration:underline"> (Tmpl*100)</span><br/>C++ </th></tr>
<tr><th class='my' align="left"> antlr </th><td class='my' align="right"> 37962 ms</td><td class='my' align="right"> 39326 ms</td><td class="highlight" align="center"> 96.53% </td><td class='my' align="right"> 37339 ms</td><td class='my' align="right"> 45151 ms</td><td class="highlight" align="center"> 82.70% </td></tr>
<tr><th class='my' align="left"> bloat </th><td class='my' align="right"> 12018 ms</td><td class='my' align="right"> 24324 ms</td><td class="highlight" align="center"> 49.41% </td><td class='my' align="right"> 13403 ms</td><td class='my' align="right"> 29218 ms</td><td class="highlight" align="center"> 45.87% </td></tr>
<tr><th class='my' align="left"> chart </th><td class='my' align="right"> 14344 ms</td><td class='my' align="right"> 17339 ms</td><td class="highlight" align="center"> 82.73% </td><td class='my' align="right"> 16610 ms</td><td class='my' align="right"> 20054 ms</td><td class="highlight" align="center"> 82.83% </td></tr>
<tr><th class='my' align="left"> eclipse </th><td class='my' align="right"> 139999 ms</td><td class='my' align="right"> 172798 ms</td><td class="highlight" align="center"> 81.02% </td><td class='my' align="right"> 154389 ms</td><td class='my' align="right"> 195541 ms</td><td class="highlight" align="center"> 78.95% </td></tr>
<tr><th class='my' align="left"> fop </th><td class='my' align="right"> 3036 ms</td><td class='my' align="right"> 3700 ms</td><td class="highlight" align="center"> 82.05% </td><td class='my' align="right"> 3382 ms</td><td class='my' align="right"> 4018 ms</td><td class="highlight" align="center"> 84.17% </td></tr>
<tr><th class='my' align="left"> hsqldb </th><td class='my' align="right"> 11258 ms</td><td class='my' align="right"> 15007 ms</td><td class="highlight" align="center"> 75.02% </td><td class='my' align="right"> 16359 ms</td><td class='my' align="right"> 20612 ms</td><td class="highlight" align="center"> 79.37% </td></tr>
<tr><th class='my' align="left"> jython </th><td class='my' align="right"> 9792 ms</td><td class='my' align="right"> 15659 ms</td><td class="highlight" align="center"> 62.53% </td><td class='my' align="right"> 11562 ms</td><td class='my' align="right"> 18601 ms</td><td class="highlight" align="center"> 62.16% </td></tr>
<tr><th class='my' align="left"> luindex </th><td class='my' align="right"> 80190 ms</td><td class='my' align="right"> 83652 ms</td><td class="highlight" align="center"> 95.86% </td><td class='my' align="right"> 82075 ms</td><td class='my' align="right"> 86279 ms</td><td class="highlight" align="center"> 95.13% </td></tr>
<tr><th class='my' align="left"> lusearch </th><td class='my' align="right"> 6692 ms</td><td class='my' align="right"> 8671 ms</td><td class="highlight" align="center"> 77.18% </td><td class='my' align="right"> 7731 ms</td><td class='my' align="right"> 9742 ms</td><td class="highlight" align="center"> 79.36% </td></tr>
<tr><th class='my' align="left"> pmd </th><td class='my' align="right"> 11364 ms</td><td class='my' align="right"> 16937 ms</td><td class="highlight" align="center"> 67.10% </td><td class='my' align="right"> 17218 ms</td><td class='my' align="right"> 23836 ms</td><td class="highlight" align="center"> 72.24% </td></tr>
<tr><th class='my' align="left"> xalan </th><td class='my' align="right"> 7901 ms</td><td class='my' align="right"> 9768 ms</td><td class="highlight" align="center"> 80.89% </td><td class='my' align="right"> 10517 ms</td><td class='my' align="right"> 13019 ms</td><td class="highlight" align="center"> 80.78% </td></tr>
<tr class="footer"><th class='my' class="footer" align="left">CmdLine</th><td class="footer" colspan="6">java [-d64 | -d32] -Xmixed -server
-Xms256m -Xmx256m -jar dacapo-2006-10-MR2.jar\<br/>-s default -n 7
antlr bloat chart eclipse fop hsqldb jython lusearch luindex pmd
xalan<br/><b>Best out of 7 runs</b> (mixed mode - need enough warmup)</td></tr> 
<tr class="footer"><th class='my' class="footer" align="left">System</th><td class="footer" colspan="6">SunOS 5.10, Sun-Fire-V440, 16GB memory, 4
UltraSPARC-IIIi CPUs at 1281 MHz</td></tr>
</table>

<p/>

<table class="my">
<caption><div class="mh3">Table 3: Interpreted and mixed mode execution on Linux/x86</div></caption>
<tr><th class='my'/><th class='my' colspan="3"> Interpreted execution (-Xint) </th><th class='my' colspan="3"> Mixed mode execution (-Xmixed) </th></tr>
<tr><th class='my'/><th class='my'> Template <br/> Interpreter </th><th class='my'> C++ <br/> Interpreter </th><th class='my'><span style="text-decoration:underline"> (Tmpl*100)</span><br/>C++ </th><th class='my'> Template <br/> Interpreter </th><th class='my'> C++ <br/> Interpreter </th><th class='my'><span style="text-decoration:underline"> (Tmpl*100)</span><br/>C++ </th></tr>
<tr><th class='my' align="left"> antlr </th><td class='my' align="right"> 58452 ms</td><td class='my' align="right"> 107494 ms</td><td class="highlight" align="center"> 54.38% </td><td class='my' align="right"> 31660 ms</td><td class='my' align="right"> 35035 ms</td><td class="highlight" align="center"> 90.37% </td></tr>
<tr><th class='my' align="left"> bloat </th><td class='my' align="right"> 136235 ms</td><td class='my' align="right"> 335865 ms</td><td class="highlight" align="center"> 40.56% </td><td class='my' align="right"> 6201 ms</td><td class='my' align="right"> 17728 ms</td><td class="highlight" align="center"> 34.98% </td></tr>
<tr><th class='my' align="left"> chart </th><td class='my' align="right"> 90805 ms</td><td class='my' align="right"> 209499 ms</td><td class="highlight" align="center"> 43.34% </td><td class='my' align="right"> 7574 ms</td><td class='my' align="right"> 11154 ms</td><td class="highlight" align="center"> 67.90% </td></tr>
<tr><th class='my' align="left"> fop </th><td class='my' align="right"> 8381 ms</td><td class='my' align="right"> 19088 ms</td><td class="highlight" align="center"> 43.91% </td><td class='my' align="right"> 1489 ms</td><td class='my' align="right"> 1956 ms</td><td class="highlight" align="center"> 76.12% </td></tr>
<tr><th class='my' align="left"> hsqldb </th><td class='my' align="right"> 32907 ms</td><td class='my' align="right"> 68857 ms</td><td class="highlight" align="center"> 47.79% </td><td class='my' align="right"> 4629 ms</td><td class='my' align="right"> 7192 ms</td><td class="highlight" align="center"> 64.36% </td></tr>
<tr><th class='my' align="left"> jython </th><td class='my' align="right"> 83621 ms</td><td class='my' align="right"> 188785 ms</td><td class="highlight" align="center"> 44.29% </td><td class='my' align="right"> 4403 ms</td><td class='my' align="right"> 8259 ms</td><td class="highlight" align="center"> 53.31% </td></tr>
<tr><th class='my' align="left"> luindex </th><td class='my' align="right"> 161362 ms</td><td class='my' align="right"> 344860 ms</td><td class="highlight" align="center"> 46.79% </td><td class='my' align="right"> 67150 ms</td><td class='my' align="right"> 73282 ms</td><td class="highlight" align="center"> 91.63% </td></tr>
<tr><th class='my' align="left"> lusearch </th><td class='my' align="right"> 33548 ms</td><td class='my' align="right"> 86230 ms</td><td class="highlight" align="center"> 38.91% </td><td class='my' align="right"> 4425 ms</td><td class='my' align="right"> 7198 ms</td><td class="highlight" align="center"> 61.48% </td></tr>
<tr><th class='my' align="left"> pmd </th><td class='my' align="right"> 69562 ms</td><td class='my' align="right"> 161983 ms</td><td class="highlight" align="center"> 42.94% </td><td class='my' align="right"> 5574 ms</td><td class='my' align="right"> 9899 ms</td><td class="highlight" align="center"> 56.31% </td></tr>
<tr><th class='my' align="left"> xalan </th><td class='my' align="right"> 49219 ms</td><td class='my' align="right"> 115101 ms</td><td class="highlight" align="center"> 42.76% </td><td class='my' align="right"> 5335 ms</td><td class='my' align="right"> 7449 ms</td><td class="highlight" align="center"> 71.62% </td></tr>
<tr class="footer"><th class='my' class="footer" align="left">CmdLine</th><td class="footer" colspan="6">java [-Xmixed | -Xint] -Xms512m -Xmx512m -server -jar dacapo-2006-10-MR2.jar\<br/>-converge antlr bloat chart eclipse fop hsqldb jython lusearch luindex pmd xalan</td></tr>
<tr class="footer"><th class='my' class="footer" align="left">System</th><td class="footer" colspan="6">SLES 9, kernel 2.6.5-7.283-bigsmp, 4GB memory, 4 Intel P4/Xeon
CPUs at 3.06GHz</td></tr>
</table>

<p/>

<p>
Although the numbers should be treated with some caution because of some
possible measurements inaccuracies, all in all the results could be
interpreted as follows. In interpreter mode (<span class="code">-Xint</span>) the
performance of the C++ interpreter varies between 35 and 50 percent of the
performance of the template interpreter. In mixed mode (<span class="code">-Xmixed</span>)
a VM that runs with the C++ interpreter reaches from 45 up to 90 percent of
the performance of a VM that runs with the template interpreter. The still
sometimes huge differences between a VM with template versus one with C++
interpreter in mixed mode, where most of the "hot" code should be compiled
anyway, may be in part explained by the lack of interpreter profiling in the
C++ interpreter (the C++ interpreter runs with
<span class="code">-XX:-ProfileInterpreter</span>). This may lead to less optimal code
generation but more details have to be further evaluated.
</p>

<p>
If you want to get more information about the current status of the C++
interpreter, you should probably follow the <a href="http://search.gmane.org/?query=C%2B%2B+Interpreter&amp;author=&amp;group=gmane.comp.java.openjdk.*&amp;sort=relevance&amp;DEFAULTOP=and&amp;query=">C++
Interpreter threads</a> on the OpenJDK Hotspot mailing list. You can also read
<a href="http://gbenson.livejournal.com">Gary Bensons online diary</a>. There
he writes about his experience of porting the OpenJDK to PowerPC using the C++
interpreter.
</p>

</body>
</html>]]>

</content>
</entry>
<entry>
<title>Testus Interruptus or how to avoid InterruptedExceptions in JCK tests</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/simonis/archive/2007/11/testus_interrup_1.html" />
<modified>2008-07-15T12:36:40Z</modified>
<issued>2007-11-13T20:12:46Z</issued>
<id>tag:weblogs.java.net,2007:/blog/simonis/427.8646</id>
<created>2007-11-13T20:12:46Z</created>
<summary type="text/plain">Although JCK tests are not a regression test suite it is probably not uncommon that they (or at least a significant subset of them) are used as automated tests. This blog describes a bug in the test agent of JTHarness that can lead to spurious test failures trough InterruptedExceptions in random tests and simple way to fix the problem.</summary>
<author>
<name>simonis</name>

<email>volker.simonis@gmail.com</email>
</author>
<dc:subject>Testing</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/simonis/">
<![CDATA[<html>

<head>

<style type="text/css" id="internalStyle">
  body {
    font-family: arial, helvetica, sans-serif;
    font-size: 10pt;
  }

  pre.listing {
    display: table;
    color: black;
    background-color: lightgray;
    border-style: solid;
    border-width: 1px;
    border-color: darkgray;
    margin: 8px 0px 5px 0px;
    padding: 2px;
    width: auto; 
    overflow: auto;  
    font-family: monospace;
  }

  .warning {
    color: red;
    font-size:  0.8em;
    text-align: center;
  }

  .mh1 {
    color: #202080;
    font-size:  1.2em;
    font-weight: bold;
  }

  .mh2 {
    color: #202080;

    font-size:  1em;
    font-weight: bold;
  }

  .mh3 {
    color: #404040;
    font-size:  1em;
    font-weight: bold;
  }

  .system {
    font-family: monospace;
  }

  .file {
    font-family: monospace;
  }

  .jdkfile {
    font-family: monospace;
  }

  .code {
    font-family: monospace;
  }

  a {
    text-decoration: none;
  }
</style>

<script language="Javascript1.5" type="text/javascript" src="http://weblogs.java.net/blog/simonis/scripts/highlight.js/highlight.js">
</script>

<title>Testus Interruptus or how to avoid InterruptedExceptions in
JCK tests</title>

</head>

<body onload="highlighter()">

<p>
Although JCK tests are not a regression test suite it is probably not uncommon
that they (or at least a significant subset of them) are used as automated
tests. To do this successfully, a number of JCK tests like for example
interactive tests or tests which require a special setup have to be excluded
from the test suite. This can be easily achieved with the help of exclude
lists.
</p>

<p>
However, even with such a setup, one still encounters infrequent, spurious test
failures in random tests. Usually, these failures are not reproducible but
still need a lot of attention in order to ensure that they do not signal a real
problem with the tested VM. 
</p>

<p>
After having analyzed such failed tests over a longer period of time I realized
that most of them have been caused by an <span class="code">InterruptedException</span> that
was not supposed to be catched within that test. Notice that while some tests
explicitely report that the reason of a failure is a catched
<span class="code">InterruptedException</span>, other tests fail silently. In such cases,
only a closer look at the test sources revealed the fact, that most of them use
to call one of the <span class="code">Object.wait()</span>, <span class="code">Thread.join()</span> or

<span class="code">Thread.sleep()</span> methods which can all be interrupted and throw an
<span class="code">InterruptedException</span>.
</p>

<p>
The only strange thing was that I couldn't identify any single call to
<span class="code">Thread.interrupt()</span> during the execution of these failed
tests. This observation led to the assumption, that the interrupts must
originate from the test agent or from the harness. Because the failures where
so seldom and occurred in random tests, I assumed that they could be provoked
by timeouts caused by a high machine load. But decreasing the JCK timeout
factor just led to more tests that where aborted. Such test are flagged with
an "Error" status in contrast to failed test which return in time but don't
return the expected result (they are flagged as "Failed"). So that obviously
wasn't the solution.
</p>

<p>
Finally, I decided to try it the hard way and instrumented
<span class="code">Thread.interrupt()</span> and the two constructors of the

<span class="code">InterruptedException</span> class to print a timestamp and a stack trace
every time they were called. After running the JCK tests with the modified VM
I could identify some interesting calls to <span class="code">Thread.interrupt()</span>:
</p>

<pre class="listing">
java.lang.Throwable: Thread.interrupt() called for Thread[Agent0,3,main]
        at java.lang.Thread.interrupt(Thread.java:821)
        at com.sun.javatest.agent.SocketConnection$1.timeout(SocketConnection.java:120)
        at com.sun.javatest.util.Timer$1.run(Timer.java:84)
</pre>

<p>
They only occurred in JCK runs with failed tests, but interestingly enough,
they sometimes happened long (up to 30 minutes) before the failing test. After
understanding the semantics of <span class="code">Thread.interrupt()</span>, which only
sets the status of a thread to "interrupted" but doesn't actively interrupt
the thread, it was clear why - the corresponding thread gets interrupted for a
yet still unknown reason, but the interrupted status of the thread is not
cleared. Afterwards, the first test which calls one of the interruptible
<span class="code">Object.wait()</span>, <span class="code">Thread.join()</span> or

<span class="code">Thread.sleep()</span> methods, will instantly raise an
<span class="code">InterruptedException</span> and fail badly.
</p>

<p>
So I just had to find out, why somebody would want to interrupt the test
thread, why this interruption happens so randomly and probably most
interesting: why isn't this interrupt handled by the test that provokes the
interrupt.  After downloading the JTHarness sources from <a href="https://jtharness.dev.java.net/">https://jtharness.dev.java.net/</a> and
digging into the code, I came up with the following explanation:
</p>

<p>
Below you can see a simplified view of how an agent handles request from the
harness (for the full story see

<a href="https://jtharness.dev.java.net/source/browse/jtharness/tags/jtharness-3_2_2-MR1-Rel-b02/code/src/com/sun/javatest/agent/Agent.java?view=markup" class="jdkfile">com/sun/javatest/agent/Agent.java</a>). For every test, the agent
establishes a new connection (an object of type <span class="code">SocketConnection</span>)
to the test harness. It receives the test name and parameters from the
connection, executes the test and returns the result back through the
connection.
</p>

<div class="mh3">Listing 1: Agent in pseudocode</div>
<div class="listing cpp"><pre class="listing">
Agent.handleRequestsUntilClosed() {
  while(!closing) {
    Connection connection = nextConnection();
    Task t = new Task(connection);
    t.handleRequest();
      // Task in pseudocode
      connection.in.readRequest();
      status = execute();
      connection.out.sendStatus(status);
      connection.out.flush();
      connection.waitUntilClosed(5000/*ms*/);
      close();
        // Task.close in pseudocode
        if (!connection.isClosed()) {
          connection.close();
	}
  }
}
</pre></div>

<p>
The interesting part here is the call to
<span class="code">connection.waitUntilClosed()</span>. The method
<span class="code">waitUntilClosed()</span> is declared in the <span class="code">Connection</span>

interface in <a href="https://jtharness.dev.java.net/source/browse/jtharness/tags/jtharness-3_2_2-MR1-Rel-b02/code/src/com/sun/javatest/agent/Connection.java?view=markup" class="jdkfile">com/sun/javatest/agent/Connection.java</a> to
potentially throw an <span class="code">InterruptedException</span>. However, the
implementation of the interface in
<a href="https://jtharness.dev.java.net/source/browse/jtharness/tags/jtharness-3_2_2-MR1-Rel-b02/code/src/com/sun/javatest/agent/SocketConnection.java?view=markup" class="jdkfile">com/sun/javatest/agent/SocketConnection.java</a> doesn't throw
any exceptions. It works as follows:
</p>

<div class="mh3">Listing 2: waitUntilClosed() in pseudocode</div>
<div class="listing cpp"><pre class="listing">
SocketConnection.waitUntilClosed(int timeout) {
  waitThread = Thread.currentThread();
  Timer.Timeable cb = new Timer.Timeable() {
    public void timeout() {
      waitThread.interrupt();
      socketInput.close();
      socketOutput.close();
    }
  };
  Timer.Entry e = timer.requestDelayedCallback(cb, timeout);
  try {
    while (true) {
      int i = socketInput.read();
      if (i == -1) break;		    
    }
  }
  finally {
    timer.cancel(e);
  }
}
</pre></div>

<p>
It first creates a <span class="code">Timeable</span> object that will interrupt the thread
and close the in- and output stream associated with the current socket after a
given amount of timeout. Thereafter it reads from the socket input stream
until it encounters an EOF condition. If the EOF is catched within the timeout
period, the <span class="code">Timeable</span> object is removed from the waiting timer
thread and the method returns. Otherwise, if the stream was not closed by the
harness within the timeout period, the timer thread will call the
<span class="code">timeout()</span> method of the <span class="code">Timeable</span> object which in
turn will call <span class="code">interrupt()</span> on the waiting thread and explicitely
close the socket streams. At this point, the thread waiting for the EOF
condition on the socket stream, will finally get it and will return. Notice
that in the latter case, the interrupt status of the thread is neither queried
and transformed into an <span class="code">InterruptedException</span> nor is it cleared.

</p>

<p>
At the end, <span class="code">handleRequest()</span>, the caller of
<span class="code">waitUntilClosed()</span> will call the <span class="code">Task.close()</span> method
that will finally close the socket. Notice that
<span class="code">handleRequest()</span> doesn't handle the interrupt status
of the thread either, so the thread will effectively stay marked as
interrupted after a timeout has happened in
<span class="code">waitUntilClosed()</span>. This will ultimately lead to a failure in the
next JCK test that calls one of the interruptible <span class="code">Object.wait()</span>,

<span class="code">Thread.join()</span> or <span class="code">Thread.sleep()</span> methods.
</p>

<p>
The solution of this problem is easy. We could either query and clear the
interrupted status of the agent thread after the call to
<span class="code">waitUntilClosed()</span> in <span class="code">handleRequest()</span>like so:
</p>

<div class="mh3">Solution 1: clear thread interrupt status in handleRequest()</div>
<div class="listing cpp"><pre class="listing">
  connection.waitUntilClosed(5000);
  if (Thread.interrupted() &amp;&amp; tracing) {
    traceOut.println("Thread was interrupted - clearing interrupted status!");
  }
</pre></div>

<p>
Notice, that the call to <span class="code">Thread.interrupted()</span> queries and clears
the interrupted status of a thread simultaneously. A slightly more elegant
solution would probably be to query and clear the interrupted status already
in the <span class="code">finally</span> block of the <span class="code">waitUntilClosed()</span> method
of <span class="code">SocketConnection</span>. In the case the thread was interrupted by
the timer thread because of a timeout, the interrupted status of the thread
should be cleared and an <span class="code">InterruptedException</span> should be
thrown. This exception will then be handled correctly in

<span class="code">Task.handleRequest()</span>.
</p>

<div class="mh3">Solution 2: clear interrupt status and throw InterruptedException in
waitUntilClosed()</div>
<div class="listing cpp"><pre class="listing">
  finally {
    timer.cancel(e);
    if (Thread.interrupted() {
      throw new InterruptedException();
    }
    ...
  }
</pre></div>

<p>
With either of these two changes, the JCK tests will run more stable on
machines with a high load an don't produce any spurious test failures because
of <span class="code">InterruptedException</span>s any more.
</p>

<p>
Notice that there's one last caveat: for some (to me yet unknown) reason, the
JTHarness 3.2.2 executes the JCK tests in a folder in a different order
than the harness that comes with the JCK test suit (and which is version
3.2_2). For example the tests in
<span class="file">/api/java_lang/management/ThreadMXBean</span> are executed in the
following order (and succeed) with the original JCK harness:
</p>

<pre class="listing">
api/java_lang/management/ThreadMXBean/index_TrdMBean_MB.jtr
api/java_lang/management/ThreadMXBean/index_TrdMBean.jtr
api/java_lang/management/ThreadMXBean/index_setTrdMBean_MB.jtr
api/java_lang/management/ThreadMXBean/index_setTrdMBean.jtr
api/java_lang/management/ThreadMXBean/index_infoTrdMBean_MB.jtr
api/java_lang/management/ThreadMXBean/index_infoTrdMBean.jtr
</pre>

<p>
With the JTHarness 3.2.2, there is one test - namely
<span class="code">TrdMBean</span> - that will fail because the <span class="code">ThreadMXBean</span>

tests are executed in a different order:
</p>

<pre class="listing">
api/java_lang/management/ThreadMXBean/index_infoTrdMBean.jtr
api/java_lang/management/ThreadMXBean/index_infoTrdMBean_MB.jtr
api/java_lang/management/ThreadMXBean/index_setTrdMBean.jtr
api/java_lang/management/ThreadMXBean/index_setTrdMBean_MB.jtr
api/java_lang/management/ThreadMXBean/index_TrdMBean.jtr
api/java_lang/management/ThreadMXBean/index_TrdMBean_MB.jtr
</pre>

<p>
To avoid this problem, the test can be placed in the exclude file. This can of
course only be done if the JCK run is not intended for certification! If
anyone of the experts knows the reason why these tests get executed in a
different order by the two versions of the test harness, please comment.
</p>

<p>
Although I'm referring to version 3.2.2 of JTHarness in this blog, the latest
version 4.1.1 suffers from the same problem. I've therefore opened a bug
report for this issue ("Bug in test agent causes random test failures (with
InterruptedException)") which got the internal review ID 1109902. If you're
interested in resolving this problem, you can vote for the bug once it appears
in the bug database.
</p>

<p>
<span class="warning">Update (2008-07-15):</span> thanks to Brian Kurotsuchi this problem has been resolved in the latest version 4.1.4 of JTHarness (see <a href="https://jtharness.dev.java.net/issues/show_bug.cgi?id=35">jtharness issue 35</a>).

</p>

</body>
</html>]]>

</content>
</entry>
<entry>
<title>Top-secret &quot;-Xintelligent_as_can_be_execution&quot; option revealed!</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/simonis/archive/2007/08/topsecret_xinte_1.html" />
<modified>2008-06-24T19:17:03Z</modified>
<issued>2007-08-30T17:19:41Z</issued>
<id>tag:weblogs.java.net,2007:/blog/simonis/427.8137</id>
<created>2007-08-30T17:19:41Z</created>
<summary type="text/plain">Recently I did some benchmarking with the HotSpot and because my program was obviously too slow, I began to browse the HotSpot sources for some secret tuning parameters that could save my day. And indeed, after some digging, I found a real big fish: the &quot;-Xintelligent_as_can_be_execution&quot; option.</summary>
<author>
<name>simonis</name>

<email>volker.simonis@gmail.com</email>
</author>
<dc:subject>Virtual Machine</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/simonis/">
<![CDATA[<html>

<head>

<style type="text/css" id="internalStyle">

  pre.listing {
    display: table;
    color: black;
    background-color: lightgray;
    border-style: solid;
    border-width: 1px;
    border-color: darkgray;
    margin: 1em 0em;
    padding: 2px;
    width: auto; 
    overflow: auto;
    font-family: monospace;
  }

  .warning {
    color: red;
    font-size:  0.8em;
    text-align: center;
  }

  .mh1 {
    color: #202080;
    font-size:  1.2em;
    font-weight: bold;
  }

  .mh2 {
    color: #202080;
    font-size:  1em;
    font-weight: bold;
  }

  .system {
    font-family: monospace;
  }

  .file {
    font-family: monospace;
  }

  .jdkfile {
    font-family: monospace;
  }

  .code {
    font-family: monospace;
    color: #202080;
  }

  a {
    text-decoration: none;
  }
</style>

<script language="Javascript1.5" type="text/javascript" src="http://weblogs.java.net/blog/simonis/scripts/highlight.js/highlight.js">
</script>

<title>Top-secret "-Xintelligent_as_can_be_execution" option revealed!</title>

</head>

<body onload="highlighter()">

<p>
Recently I did some benchmarking with the HotSpot and because my program was
obviously too slow, I began to browse the HotSpot sources for some secret

tuning parameters that could save my day. And indeed, after some digging, I
found a real big fish: the "<span class="code">-Xintelligent_as_can_be_execution</span>"
option.
</p>

<p>
Well, sounds extremely promising, I thought by myself, and started some
experiments. For your convenience, I'll reproduce here the small factorial
program, that I used to measure performance:
</p>

<div class="listing java"><pre class="listing">
import java.math.BigInteger;

public class Factorial {

  public static BigInteger factorial(long l) {
    BigInteger result = BigInteger.ONE;
    BigInteger fac = BigInteger.ONE;
    while (l-- &gt; 0) {
      result = result.multiply(fac);
      fac = fac.add(BigInteger.ONE);
    }
    return result;
  }

  public static void main(String args[]) {
    long l = args.length &gt; 0 ? Long.parseLong(args[0]) : 1;
    long t1 = System.currentTimeMillis();
    System.out.println("Factorial " + l + " = " + factorial(l));
    System.err.println("Elapsed time = " + 
                       (System.currentTimeMillis() - t1) + "ms");
  }
}
</pre></div>

<p>
I compiled the program and started Java on the console (I redirected the
output of the resulting number to <span class="file">/dev/null</span> to display only the
elapsed time):
</p>

<pre class="listing">
&gt; java Factorial 10000 &gt;/dev/null
Elapsed time = 2579ms
</pre>

<p>
Now the same program with the secret
"<span class="code">-Xintelligent_as_can_be_execution</span>" option. Big expectations...
</p>

<pre class="listing">
&gt; java -Xintelligent_as_can_be_execution Factorial 10000 &gt;/dev/null
Elapsed time = 14930ms
</pre>

<p>
...big frustration. The execution time has increased by a factor of five! What's
wrong here? If you can't belive it, just trust me and try the option with your
preferred application. A performance degradation is guaranteed.
</p>

<p>
But what is this <em>intelligence</em> option good for, if it only slows down a
program? So I started further investigations and found another very
interesting, undocumented (and therefore probably extremely striking) option:
"<span class="code">-Xcompletely_brain_damaged_execution</span>". Seems counterintuitive,
but if the "<span class="code">-Xintelligent_as_can_be_execution</span>" option slows the
program down, perhaps the "<span class="code">-Xcompletely_brain_damaged_execution</span>"
option will accelerate execution time up to infinity?
</p>

<pre class="listing">
&gt; java -Xintelligent_as_can_be_execution \
       -Xcompletely_brain_damaged_execution Factorial 10000 &gt;/dev/null
Elapsed time = 2599ms
</pre>

<p>
Well, not exactly brilliant, but at least the <em>brain damage</em> option
seems to compensate for the <em>intelligence</em> option. Finally I decided to
abandon the search for secret high performance options and back-doors intended
only for the use by the coalition of the willing and other registered secrete
services and just went on improving my own program...
</p>

<p>
<div class="warning">This is my first blog on java.net and I thought I'll start with
something funny..</div>
<p>

<p>
If you didn't knew the two <em>secret</em> options discussed just before you
don't have to be upset. The funny thing is that they really work as described
(I hope you tried them out), but as in the majority of cases, there's a really
trivial explanation for this phenomena.
</p>

<p>
As you probably know, the HotSpot VM supports some extended options, among
them "<span class="code">-Xint</span>" and "<span class="code">-Xcomp</span>". The first one runs the VM
in an interpreter-only mode (without JIT compilation) while the latter advises
the VM to compile all Java methods before executing them. For some reason
(probably accidentally - or intentionally if you like to belive in
conspiracy), the HotSpot programmers decided to match the original options
against the beginning of a given command line argument (in fact they use
<span class="code">strncmp()</span> with the length argument being set to the length of
the original option). Therefore, the
"<span class="code">-Xintelligent_as_can_be_execution</span>" option is recognized as
"<span class="code">-Xint</span>" while the
"<span class="code">-Xcompletely_brain_damaged_execution</span>" option is identified as
"<span class="code">-Xcomp</span>".
</p>

<p>
Obviously, the execution of a program in interpreter-only mode is considerably
slower than the execution in mixed mode (which is the default mode). On the
other hand, "<span class="code">-Xint</span>" and "<span class="code">-Xcomp</span>" are mutually
exclusive options. If they are given both on the command line, the last one
wins. That's why in the last example, we ended in the compile-all
mode. Usually, the execution time in this mode is slightly slower than in
mixed mode, because each and every Java method will be JIT-compiled. In our
small example however, the execution time was similar to the one in mixed
mode.
</p>
</body>
</html>]]>

</content>
</entry>

</feed>