Skip to main content

Compiling the JMX API in Mustang

Posted by emcmanus on August 30, 2005 at 9:10 AM PDT

The Java SE sources are downloadable from java.net, and you can
change and extend them within the constraints of the relevant
licenses. But building the whole of Java SE is a major
undertaking. Here's how to build just the JMX API. The same
ideas would apply to building other subsets of Java SE that are
Java-language-only.

Update: there is now a purpose-designed build.xml that ships
with the Mustang sources and that provides a simpler alternative to what's
described here for the JMX API. See
Joël Féraud's blog
. But the process described here is
still useful for building other subsets of the Mustang API.

Why is this interesting?

There are a number of reasons why you might be interested in
modifying and recompiling the Java SE sources:

  • For research purposes, as covered by the href="http://java.net/jrl.html">Java Research License
    (JRL). This might be for your own curiosity ("I bet I
    could speed up the MBeanServer implementation"). Or it
    could be a good idea for a student project ("Add support for
    persistence to the JMX API"; "Extend the JMX API to provide
    support for reliable eventing"). Student projects that
    modify an existing medium-sized code base like the JMX API
    are much more instructive than projects that create new code
    from scratch, as they teach the invaluable skills of finding
    your way around a body of code. (I have lots more ideas for
    student projects, by the way!)

  • As an extension to the previous idea, you may be
    interested in href="http://java.sun.com/developer/technicalArticles/J2SE/peabody/">
    contributing to the JDK code base. Obviously if you
    want to do this, you'll need to be able to build your
    modifications or extensions to existing code.

  • Finally, you might have run into a critical problem in
    the JMX API that you need to be able to fix right away. In
    general we make every effort to fix blocking problems
    promptly when they are reported, but because of the standard
    release cycle, it could be a few months before you see an
    update with your problem fixed. If you need the fix
    right now then you may be able to make it yourself
    under the terms of the
    Java Internal Use License (JIUL)
    .

The JIUL applies to the current released JDK version, JDK 5.0
("Tiger"), so the third reason above only applies there. The
JRL applies to both Tiger and the forthcoming version, JDK 6
(Mustang), so for research you can choose which one is more
appropriate. You can potentially contribute bugfixes and
performance optimizations to Tiger or Mustang, though it's
likely to be easier to contribute to Mustang. You can only
contribute API changes to Mustang, since the Tiger API is
frozen.

I should note that I am not a lawyer, and I'm not a
spokesperson for Sun either, so read the licenses and their FAQs
to be sure they cover what you want to do.

How do I build a subset of the JDK sources?

The instructions below are for building the JMX API in Mustang.
Building a subset of Tiger is actually somewhat simpler, because
you do not need to worry about "cross-platform support".

Apart from the details about RMI stubs at the end, the same
considerations would apply to building other Java-language
subsets of the JDK sources. If you need to change native code,
then things become more complicated. Fortunately the JMX API
doesn't contain any native code.

I tried out everything here on a machine running Microsoft
Windows 2000. My usual development environment is Solaris, so
trying this out on Microsoft Windows should have helped me avoid
missing any "obvious" details that might not be so obvious to
people who haven't worked on the JDK sources before! If you're
running on a Unix-like environment such as Solaris or Linux it
should be fairly obvious what to change.

  • To build Mustang, you'll want Mustang's JDK installation.
    This is all the more true if you are only building part of
    Mustang, because the JDK installation will supply the part
    you're not building. Download and install the latest
    Mustang JDK binaries from

    http://download.java.net/jdk6/binaries/
    .

    Check the click-through license -- this is pre-release
    software and that limits what you can do with it, in obvious
    ways.

    You probably don't want to install this JDK snapshot in the
    default location. On Microsoft Windows, it is
    C:\Program Files\Java\jdk1.6.0\, which I think
    confers an unwarranted legitimacy on the installation. I
    put it in D:\jdk1.6.0\ -- you get to choose this
    in the dialogue entitled "Custom Setup". You don't need to
    change anything else in this dialogue.

    The installer covers both the Java SE Development Kit (JDK)
    and the Java SE Runtime Environment (JRE). In the "Custom
    Setup" dialogue for the JRE, you'll likewise probably want
    to change the default install location.
    D:\jre1.6.0\ was the location I chose.

  • Download the latest Mustang source from

    http://download.java.net/jdk6/
    . You'll
    need "JDK 6.0 Source under the href="http://www.java.net/jrl.csp">JRL License", and
    you should take a moment to check out the license.

    The "JDK Binaries for Source Build 6.0" represents binary
    files such as Swing icons. You don't need these if you are
    building the JMX API, but if you're following these
    instructions to build some other subsystem you might.

    The source snapshot you downloaded will be called something
    like jdk-6_0-ea-src-b49-jrl-25_aug_2005.jar.
    It is an executable jar file. On Unix-like systems you
    might need to make it executable (

    chmod +x
      filename
    ). Then execute it to install the complete
    Mustang sources.

    You get another chance to look at the magnificent JRL
    License before you click to accept it. Then you specify where
    you want to install the sources. I put this snapshot (b49) in
    D:\mustang-src-b49 to avoid confusion with any
    other Mustang snapshots I might download, but you might prefer
    to reuse the same directory even if you download several
    snapshots.

  • There's a huge amount of source code in this snapshot.
    To find your way around a bit, check out the
    README.
    All we're interested in here is the parts that build the JMX
    API.

    OS-independent Java platform classes can be found under
    j2se\src\share\classes. Frequently, subsystems
    have some classes under java.* or
    javax.*, including all of the publicly-visible
    API classes of course; and some implementation classes under
    sun.* or com.sun.*. You can find
    out pretty readily where this second set of classes lives by
    examining the import statements in the first set.

    It turns out that the complete set of sources needed to
    build the JMX API consists of:

    • All classes under javax.management,
      including all subpackages, such as
      javax.management.timer and
      javax.management.remote.
    • All classes under com.sun.jmx, including
      all subpackages except
      com.sun.jmx.snmp.
      com.sun.jmx.snmp represents the source for SNMP
      access to the JVM instrumentation defined by
      JSR 174; this
      is not directly relevant to the JMX API. You can build it
      if you want, but you don't need to.
  • I'd suggest copying the subset you want to build into a
    different directory rather than trying to build the files within
    the complete hierarchy. What I did was to create another
    directory D:\mustang-jmx-src-b49 with a
    subdirectory src into which I copied the
    javax\management and com\sun\jmx
    hierarchies. (Then I removed com\sun\jmx\snmp.)
    Of course you need to preserve the directory hierarchy, e.g. you
    should have src\javax\management and
    src\com\sun\jmx within your subset directory.

  • You now have a workspace within which you can build the
    JMX API. Here's how I went about it using NetBeans 4.1. I
    would expect the steps would be similar with other IDEs,
    although if your IDE does not support cross-platform use
    things will be a bit tricky. Cross-platform means that for
    example I am running NetBeans using JDK version 5.0 but I am
    telling it to compile and run my sources using JDK version
    6. If your IDE doesn't support cross-platform use then you
    might still be able to run it under the JDK 6 snapshot you
    have downloaded. This is not necessarily as scary as it
    sounds -- at work I usually run NetBeans with the latest
    Mustang snapshot and there's only been one period of two
    weeks where it didn't work well. But, nothing is guaranteed
    with these snapshots, and the fact that the class file
    format has changed in Mustang may prevent your IDE from
    being able to compile against the JDK classes.

  • I first created a NetBeans project using File -> New
    Project -> Java Project With Existing Sources. I specified
    project name mustang-jmx-src-b49 and project
    directory D:\mustang-jmx-src-b49, i.e. the
    directory where I had copied the source subset. I added the
    src subdirectory in the dialogue that says "Specify
    the folders containing the source packages and JUnit test
    packages." I specified a new test subdirectory for
    JUnit tests. Once I clicked on "Finish" the project was created.

  • Then I set up cross-platform building and running.
    NetBeans is running on JDK version 5.0 but I want it to use the JDK 6
    snapshot to compile and run the sources of this project. So I
    right-clicked on my mustang-jmx-src-b49 project in
    the Projects pane, and selected Project Properties -> Libraries.
    I needed to tell
    NetBeans about the JDK 6 platform, which I did using the "Manage
    Platforms" button on the top right of this dialogue. (You can
    also use Tools -> Java Platform Manager.) In the Java
    Platform Manager dialogue, I clicked "Add Platform..." in the
    bottom right. I selected D:\jdk1.6.0, which you'll
    remember is where I installed the downloaded Mustang JDK
    snapshot. If you downloaded the snapshot Javadoc you could
    specify it here too, but you don't have to. (I usually browse
    it directly from

    java.net
    .) Then Finish (for Add Platform) and Close
    (for Java Platform Manager), and you're back to Project
    Properties. You can now select the JDK 6 platform in the
    Java Platform drop-down list.

  • Also within the Project Properties dialogue, I needed to
    tell NetBeans to use compiled classes from within the
    project in preference to the classes in the JDK
    installation. This is subtle but important. Even if you
    have a class called javax.management.ObjectName
    in your classpath, the Java compiler and runtime will never
    see it because they will find the class of the same name in
    the JDK installation first. You need to change
    the boot classpath using
    the
    -Xbootclasspath
    option for both compiling and
    running.

    In Project Properties -> Build -> Compiling, I put
    the following in the "Additional Compiler Options":

    -Xbootclasspath/p:build/classes

    build/classes is the subdirectory within the
    workspace where NetBeans is going to put its compiled classes.
    (If you want to be squeaky clean you could put
    ${build.classes.dir} here instead.)
    The /p means "prepend", i.e. this directory will
    be put in the boot classpath before the standard classes,
    which is what you want. I put the same thing in the "VM
    Options" within Project Properties -> Run.

  • Unfortunately it appears that this
    -Xbootclasspath option doesn't get applied to
    the Java VM that is running the JUnit command to run tests.
    I had to edit some ant files by hand. I copied from
    nbproject\build-impl.xml the complete set of
    lines from

    <target
        name="-init-macrodef-junit">

    through to the
    corresponding </target>, and pasted them
    into the top-level build.xml file near the end. Then I
    added this line in the pasted text, just after the
    <junit ...> line:

    <jvmarg value="-Xbootclasspath/p:build/classes" />
  • Now to test that NetBeans really is compiling my sources
    and not falling back on the JDK classes, I added a trivial
    main method to
    javax.management.ObjectName:

        public static void main(String[] args) {
            System.out.println("hello, world");
        }

    NetBeans now flags ObjectName.java with a
    little green arrow in the Projects or Files panel because it
    is runnable. If I right-click on ObjectName.java
    in the panel, I can do "Run file". If this works, I know
    NetBeans is compiling and running my modified
    ObjectName class.

    Similarly, I can code a trivial JUnit test using File ->
    New File -> JUnit -> Empty Test. I just insert a test
    method that calls my new ObjectName.main
    method:

        public void testObjectNameMain() {
            ObjectName.main(new String[0]);
        }

    Now "Run file" on the test should successfully execute my
    test and print "hello, world".

  • If you've followed all these steps, you're now set up to
    play with the JMX API sources!

    One thing to watch out for, though, is that if you delete
    or rename a class, the compiler will still be able to find
    it in the original JDK classes. So if there are still
    references to the deleted class, they will continue to
    compile! If this proves to be a serious problem, you can
    get around it by preparing a "JMX-less" JDK installation.
    Copy your original JDK installation to another directory,
    and remove the javax.management and
    com.sun.jmx packages and subpackages from
    jre\lib\rt.jar within that other installation.
    The jar command doesn't allow you to remove
    things from a jar, but because a jar is a special kind of
    zip file, you can use any tool for manipulating zip files
    instead. Then use the Java Platform Manager within NetBeans
    to replace the original JDK 6 platform with your JMX-less
    JDK platform. On the whole, this is a dodgy manoeuvre, and
    it's not guaranteed to work in the future. However, it's
    what we do within the JMX API team at Sun, and if it stops
    working at some point, I'll update this page. Also, I'd
    expect it probably wouldn't work for classes that the
    compiler itself needs to run. The compiler doesn't need the
    JMX API, but you might have a hard time doing the same thing
    with java.util!

  • A final thing to watch out for is that the JMX Remote API
    includes some RMI stubs which are built using the href="http://download.java.net/jdk6/docs/tooldocs/windows/rmic.html">
    rmic tool. Since the source for these
    generated stubs is not included in the JDK source
    download, you will contine to pick them up from the JDK's
    own classes. If you make a JMX-less JDK installation, or if you want to
    change the RMI interfaces the stubs come from ( href="http://download.java.net/jdk6/doc/api/javax/management/remote/rmi/RMIServer.html">
    RMIServer and href="http://download.java.net/jdk6/doc/api/javax/management/remote/rmi/RMIConnection.html">
    RMIConnection), then for the JMX Remote
    API to work you'll need to generate the stubs yourself.

    You could add some href="http://ant.apache.org/manual/CoreTasks/rmic.html">
    <rmic> tasks to your
    build.xml, but it might be simpler just to
    generate the source code for the stubs and include the
    source in your project. For example, to make the
    RMIServer stub source you could use:

    rmic -keep -d src -bootclasspath build\classes;D:\jdk1.6.0\jre\lib\rt.jar
         javax.management.remote.rmi.RMIServerImpl

    (all on one line of course), then remove the file
    src\javax\management\remote\rmi\RMIServerImpl_Stub.class
    that rmic will have generated. The procedure is
    the same for the RMI/IIOP stubs except you need the
    -iiop option and the stubs will be generated in
    org\omg\stub\javax\management\remote\rmi.
    Unfortunately rmic doesn't recognize
    -Xbootclasspath/p: so you have to give the full
    path to the classes in your JDK installation as shown
    here.

I hope this has been helpful! If you had a problem following
these instructions, or would like to suggest improvements, or if
you want to discuss API changes you are interested in, feel free
to contact me at

jmx-spec-comments@sun.com
.

Update: if you want to build the whole of the JDK on a
Microsoft Windows platform, Kelly O'Hair has documented out how to do it. The hard part is installing the necessary software.

Related Topics >>