A Complicated Slide?
2008-06-11 11:19:12
This Dilbert comic strip reminded me of a drawing I did a while back to try and explain the critical nature of our bug tracking system, and how all the various systems we have and use connect back to the bug database. Granted, right now the JDK team is using an internal bug tracking system (that will change someday), and the visibility is limited to what you can see via http://bugs.sun.com/.
The complicated drawing below is mine alone and is not an official JDK drawing and is undoubtedly not 100% correct, it is just my attempt to convey some of the connections to our bug tracking system:
And a few terms to define the words used:
I hope this helps someone and doesn't really confuse people. And no, the rocket ship is not blasting the webrevs. :^)
-kto
My First OpenJDK7 Mercurial Push
2008-06-09 09:18:15
Finally was able to push my first OpenJDK7 Changes into the Mercurial jdk7/build area forest. Specifically to the three repositories: jdk7/build/jdk jdk7/build/jdk, and jdk7/build/jdk.
You can actually browse the changesets by clicking on the changeset links. If you haven't browsed around a Mercurial repository, it's pretty cool.
This is just one of the many team areas for the JDK7 project, as the build team changes accumulate, at some point we will decide (as a team) to do some more detailed build&test; runs and when we are satisfied all is well, we will reserve a time to integrate all these build changes to the master area Mercurial forest at http://hg.openjdk.java.net/jdk7/jdk7. (The various teams have to take turns integrating to the master area).
Finally, at some point the Release Engineering team will do their thing and create formal promoted builds from the master repositories, tagging the repositories to indicate when the promotion took place. The Release Engineering team will have to push the tag additions to the master repositories as a final step. At that point, cloning the repositories using that specific tag should get you the exact source used to create the promoted build.
Things are heating up in the OpenJDK world... ;^)
-kto
NetBeans, Mercurial, Ant, Mac OS X, and getting the right PATH set
2008-06-09 02:18:43
It took be some time, but I figured out how to change the environment variables that the launched Mac applications will get. Why? Because I wanted NetBeans to be running with a PATH environment variable setting that matched what Ant got when I used the build.xml file from the command line. When running the "<exec>" Ant task to use an executable, full paths or modifying the PATH is very platform specific, hard to maintain, and a huge pain. Having the PATH set properly in the environment is the best way.
Now I could launch "netbeans" from a command line and it would work, but here is the answer for setting the environment for applications launched:
cat ~/.MacOSX/environment.plist
{
PATH = "/Users/ohair/ant/bin:/Users/ohair/findbugs/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/sbin:/sbin";
}
The directory ~/.MacOSX will need to be created. Apparently this file is read in at login time, so if you change it you will need to logout and log back in again for any change to make a difference. In my case I added the path to my Ant, my Findbugs, and /usr/local/bin which contains the Mercurial (hg) I want to have available in the PATH. I'm not sure NetBeans will actually use the version of Ant in the PATH, but that hasn't been an issue for me.
It was the need for /usr/local/bin (hg) in the path (/usr/local/bin) that got me started on all this because in my Ant file I wanted the build to automatically pull the version information out of the repository and make it available to the built product as a property setting. Effectively I need to run:
# Get the last changeset
hg tip --template '{node|short}\n'
# Get the latest tag with a Version string in it
hg log -l 1 --template '{desc|firstline}\n' -k "Version:"
# Get the date of the last changeset
hg tip --template '{date|shortdate}\n'
I used Ant rules something like this:
<target name="hgpropfile" description="Create property file">
<exec executable="hg" outputproperty="hg.tip.id">
<arg value="tip"/>
<arg value="--template"/>
<arg value="{node|short}\n"/>
</exec>
<exec executable="hg" outputproperty="hg.last.tag.summary">
<arg value="log"/>
<arg value="-l"/>
<arg value="1"/>
<arg value="-k"/>
<arg value="Version:"/>
<arg value="--template"/>
<arg value="{desc|firstline}\n"/>
</exec>
<exec executable="hg" outputproperty="hg.tip.date">
<arg value="tip"/>
<arg value="--template"/>
<arg value="{date|shortdate}\n"/>
</exec>
<!-- Indentation is critical here -->
<echo file="${dist.dir}/config-default.properties" append="false">
product.version=${hg.tip.date} ${hg.last.tag.summary} [${hg.tip.id}]
</echo>
</target>
This property and it's value would need to be read in or made available at runtime, the
actual Java code would just need to getProperty("product.version") to get the
version string.
I used a tag to track the version code name, with the most recent tag containing "Version:" provides the product code name. The date and changeset id come from the tip, or most recent changeset.
Automating the creation of a new version code name tag can be done with a special Ant target used when needed. Effectively it needs to run:
hg tag -f -m "Version: Name" TAG-YYYY-MM-DD
I just created a file with a few hundred code names and pick one based on the
day of the year.
The Ant target looks something like:
<target name="new_version" description="Create new version tag">
<tstamp>
<format property="date.year.day" pattern="D"/>
</tstamp>
<tstamp>
<format property="date.ymd" pattern="yyyy-MM-dd"/>
</tstamp>
<property name="versions.file" value="AllVersions"/>
<exec executable="wc" outputproperty="version.count.temp" input="${versions.file}">
<arg value="-l"/>
</exec>
<exec executable="sed" outputproperty="version.count" inputstring="${version.count.temp}">
<arg value="-e"/>
<arg value="s@^[\ ]*\([1-9][0-9]*\)$@\1@"/>
</exec>
<exec executable="expr" outputproperty="version.selection">
<arg value="${date.year.day}"/>
<arg value="%"/>
<arg value="${version.count}"/>
</exec>
<exec executable="sed" outputproperty="version.name" input="${versions.file}">
<arg value="-e"/>
<arg value="${version.selection},${version.selection}p"/>
<arg value="-n"/>
</exec>
<exec executable="hg">
<arg value="tag"/>
<arg value="-f"/>
<arg value="-m"/>
<arg value="Version: ${version.name}"/>
<arg value="TAG${date.ymd}"/>
</exec>
</target>
Or in a Makefile you could do a similar thing:
DATE_YEAR_DAY:=$(shell date +%j)
DATE_YMD:=$(shell date +%Y-%m-%d)
VERSIONS_FILE=AllVersions
VERSION_COUNT:=$(shell cat $(VERSIONS_FILE) | wc -l | sed -e 's@^[\ ]*\([1-9][0-9]*\)$@\1@')
VERSION_SELECTION:=$(shell expr $(DATE_YEAR_DAY) '%' $(VERSION_COUNT))
VERSION_NAME:=$(shell cat $(VERSIONS_FILE) | sed -n -e "$(VERSION_SELECTION),$(VERSION_SELECTION)p" -n)
new_version:
hg tag -f -m "Version: $(VERSION_NAME)" TAG$(DATE_YMD)
Now creating tags like this may not be advised or necessary with all repositories, but the basic principle can work in many situations. For example, with the OpenJDK project, the Release Engineering people will create the major milestone tags, and using those you could effectively identify a JDK version with a name (e.g. JDK 7 Build 23), and an exact changeset id. The trick is to get the version information from the repository, into the build tool (make or ant), into the product installation or baked into the product executable, and then available at runtime by the product plus easily seen when looking at an installation of the product. One issue I see is dealing with the situation where you are building a plain source tree without the Mercurial data or the Mercurial tools, somehow when the plain source tree is created the version data would need to be left in the source bundle.
Hope this is of some use to people. I'm sure there might be a better way, so if anyone has
any ideas please add your comments.
Ultimately I'd like a product to be able to provide enough details to a user
so that the original source tree could be made quickly available.
Given the changeset id, the exact and complete source could be re-created
with hg clone --rev, of course that gets more complicated with
a forest, but still pretty simple.
-kto
A Short java_crw_demo User Guide
2008-06-09 02:18:43
The java_crw_demo library is provided as a native code (C) demo of a BCI library that can instrument class files. It is just a demo, but an operating demo in that it has been used in the hprof VM agent and various JVM TI demo agents delivered in the OpenJDK JVM TI Demo Sources (typically the built versions of these demos are in the JDK installed on your system in the demo/jvmti directory). The complete code to java_crw_demo can be found in the OpenJDK Mercurial Repository. In particular, the #include file java_crw_demo.h is of primary interest.
A complete description of the class file format can be found in Chapter 4 of the Java Virtual Machine Specification (or look at the wikipedia entry on the class file format). Only part of the class file needs to be modified for basic instrumentation: the Code attribute (including the max-stack field), the constant pool, the Exception Table, the LineNumberTable, the LocalVariableTable, the LocalVariableTypeTable, the StackMapTable, and any StackMap attributes. The java_crw_demo does not add methods or fields and does not change the exception data except to adjust the pc offsets or byte offsets in the exception table. In fact the basic Table changes are just the pc or byteoffset adjustments. Any instrumentation more detailed than this would best be done with something other than a demo library like java_crw_demo, something more like ASM or BCEL would make much more sense.
Please keep in mind this is just a demo library, and fairly primitive in what it can do. It's functionality was driven by what hprof needed to do, e.g. instrument method entry and exit, and instrument memory allocations.
Basically there are just two functions in this library:
void java_crw_demo(
unsigned class_number,
const char * name,
const unsigned char * file_image,
long file_len,
int system_class,
char * tclass_name,
char * tclass_sig,
char * call_name,
char * call_sig,
char * return_name,
char * return_sig,
char * obj_init_name,
char * obj_init_sig,
char * newarray_name,
char * newarray_sig,
unsigned char ** pnew_file_image,
long * pnew_file_len,
FatalErrorHandler fatal_error_handler,
MethodNumberRegister mnum_callback);
char * java_crw_demo_classname(
const unsigned char * file_image,
long file_len,
FatalErrorHandler fatal_error_handler);
The java_crw_demo_classname method is used to extract out the classname from
a class file.
In some cases classes are loaded into the VM without a name (see
defineClass method in java.lang.ClassLoader.)
The java_crw_demo is the function you can call with a class file image and get
back an instrumented class file image. The arguments are defined below:
It's assumed that the JVM TI agent code would request some kind of class load event, a good example is the heapTracker demo. When it gets a CLASS FILE LOAD HOOK event, it effectively passes in the class image to java_crw_demo:
newImage = NULL;
newLength = 0;
java_crw_demo(cnum, classname,
class_data, class_data_len, systemClass,
"HeapTracker", "LHeapTracker;",
NULL, NULL,
NULL, NULL,
"newobj", "(Ljava/lang/Object;)V",
"newarr", "(Ljava/lang/Object;)V",
&newImage;, &newLength;,
NULL, NULL);
Which only does instrumentation for object allocations and doesn't use the callbacks.
This demo doesn't fully use java_crw_demo like hprof, the hprof Tracker class is a complete Tracker class, while the heapTracker class is just a partial tracking class. The VM agent needs to implement and register the native methods for these Tracker classes.
The Tracker class doesn't have to use native methods, but since hprof was a native code agent, and most VM agents are native code, somehow the information captured via the class file instrumentation needs to get back into the native agent anyway.
A pure java VM agent via the java agent mechanisms is probably a better way to go, but at this time I don't have a simple demo of the java agent.
-kto
Why is NetBeans so slow? Here is a tip.
2008-06-09 02:18:43
I use NetBeans 6 all the time on my Mac laptop and have learned how to configure it to run more effectively for me. NetBeans, like any Java application needs room to work, and the default memory settings for Java and NetBeans are usually not what I consider ideal. Of course how would they know what is ideal, you need to tell it. Granted my solution may not be ideal for others, but it's worth playing with. I'm using jdk5 update 13 on my Mac, but these same setting should apply to jdk6 also. And it's not just for The Mac or even NetBeans 6, this should work on any platform.
KellyMacBook<3> cat ~/.netbeans/6.0/etc/netbeans.conf
netbeans_default_options="-J-Xms256m -J-Xmx512m -J-XX:PermSize=32m -J-XX:MaxPermSize=160m
-J-Xverify:none -J-Dapple.laf.useScreenMenuBar=true -J-XX:+UseConcMarkSweepGC
-J-XX:+CMSClassUnloadingEnabled -J-XX:+CMSPermGenSweepingEnabled"
Any change to this file will require a reboot (there should be one line in the file above, I had to break it up to get the blog to display it in a readable way).
Also, turn on the View->Toolbars->Memory to keep track of the NetBeans memory usage, clicking on it will force a GC, and you can get a feeling for how much memory your NetBeans session needs, making adjustments to the maximums above. And my recommendation is that the maximum (-J-Xmx) setting should never be more than the RAM on the machine minus 512m, or system memory thrashing may occur.
Additional information can be found at the NetBeans FAQ on GC pauses and the NetBeans FAQ on configuration.
The above settings make a world of difference in the way NetBeans performs for me.
-kto
Following The Rules
2008-06-09 02:18:43
With the recent release of the OpenJDK Developer Guide, I'm remembering Sister Dennis Anne from my grade school days. I never got the ruler slapped over the back of my hands, well, not very often, but my older brother practically had a ruler tatoo on his hands. Ouch. :^(
Now it's not all that bad, but I'm sure some of you have been thinking it is. Even Sister Dennis Anne didn't slap that ruler needlessly, well maybe my brother was a special case, he usually deserved it. ;^) Fortunately, the rules belong to us, not the Sisters.
In any case, please subscribe to the alias guide-discuss@openjdk.java.net if you'd like to make comments about the guide or discuss it.
-kto
P.S. Picture courtesy of listverse.com.
OpenJDK Bug States
2008-05-11 12:48:07
Until the OpenJDK project converts to Bugzilla, I thought some more information about how our internal bug tracking system works might help people watching the current situation.
The OpenJDK change requests (CRs) or bugs are currently visible at bugs.sun.com.
There are 11 states for a CR and the normal change of state is the following:
The states 1-9 are considered "unresolved", so until a bug becomes "10 - Fix Delivered" or "11 - Closed", it is still considered unresolved. So being "unresolved" may mean that a fix is available, just not in a position to be made part of a formal build promotion.
The bugs.sun.com interface is read-only and somewhat crude, but you can query the bug information, for example the Unresolved JDK Build Subcategory Bugs and RFEs. Hope this helps explain things.
-kto
Sun Studio Compilers on LINUX?
2008-05-07 12:48:42
With the magic of Mercurial, you can see changesets, like this one: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/rev/485d403e94e1. Which Serguei Spitsyn integrated recently.
But wait, what does this changeset actually mean? Sun Studio on Linux? Does that make sense? YES! It does and it's true. Mind you, it's just Hotspot that can be built with the Sun Studio compilers on Linux right now, but it's an important piece, the Hotspot C++ code is not a trivial pile of code to compile and optimize correctly. My hat is off to the Sun Studio team in making this all happen. What should be interesting now is how well the rest of the tools work like dbx and the analyzer/collector.
More can be read about the Sun Studio Linux Compilers at the Sun Studio Site.
Humm, I guess I'm now on the hook to see if the rest of the OpenJDK can be setup to build with Sun Studio on Linux.... Back to work...
-kto
P.S. No, we are not abandoning gcc/g++, just providing choices on how the OpenJDK can be built.
InfoQ Article on Git, Mercurial, and Bzr
2008-05-07 12:19:38
A while back Sébastien Auvray asked me some questions about the OpenJDK Mercurial conversion. His article was recently published at http://www.infoq.com/articles/dvcs-guide.
Has some interesting information and stats about Git, Mercurial, and Bzr.
-kto
Windows, cygwin, mks, java, and a lump of coal
2008-04-30 18:48:04
I've been trying to setup a system that could easily switch between using MKS and CYGWIN, and also run from a Java program... what a pain.
Some of the issues I've run into:
At this point, at least on Windows, I'm not too crazy about trying to get all these things to work well together. I may completely avoid shells on Windows from now on, it's like getting a lump of coal for XMAS. :^(
-kto
P.S. I see in a comment that I may have discouraged people from using cygwin, I did not mean to do that. Either MKS or cygwin on it's own, or mixed with Java is very possible, heck anything is possible. And I suspect there are other Windows Unix tool sets that would work just fine. The problem I was having was when they all got mixed together in a process chain. Creating a shell script that works with in either a MKS bash session and a cygwin bash session is quite possible, and not too messy. But having these two shell processes be connected is another story. I actually prefer cygwin even with the differences in PIDs and the pathname/PATH issues because it seems to behave like Unix, the ps and kill seem to be reliable. We have used MKS for a long time, and basically have been happy with it, our only issue is that it is not free for our OpenJDK users. So we are trying to convert to cygwin where we can, but bridging between the two at runtime is the most difficult.