The Source for Java Technology Collaboration
User: Password:



Eamonn McManus's Blog

Eamonn McManus Eamonn McManus is the technical lead of the JMX team at Sun Microsystems. As such he heads the technical work on JSR 255 (JMX API 2.0) and JSR 262 (Web Services Connector for JMX Agents). In a previous life, he worked at the Open Software Foundation's Research Institute on the Mach microkernel and countless other things, including a TCP/IP stack written in Java. In an even previouser life, he worked on modem firmware in Z80 assembler. He is Irish, but lives and works in France and in French. His first name is pronounced Aymun (more or less) and is correctly written with an acute accent on the first letter, which however he long ago despaired of getting intact through computer systems.



JMX technology and NetBeans

Posted by emcmanus on November 08, 2005 at 10:32 AM | Permalink | Comments (0)

There's a plugin for NetBeans that supports the JMX API. It allows you to create and modify JMX MBeans through a wizard, to create unit tests for them, and to run an application and simultaneously attach to its JMX instrumentation. My colleague Jean-François Denise writes about this and more in a recent blog entry, with pointers to some excellent tutorials.

Excellent article by Ron Bodkin about using AspectJ and JMX technologies for monitoring

Posted by emcmanus on November 05, 2005 at 05:53 AM | Permalink | Comments (0)

Ron Bodkin has written an excellent, detailed article about using the Glassbox Inspector project. This combines AspectJ and JMX technologies to add monitoring to applications in a clean and modular way.

I particularly like this style of article, where extended code extracts are used to present something really useful rather than just a toy example. The alternating text and code reminds me of Literate Programming.

While much has been written about the possible abuses of AOP, most of it focuses on cases where AOP is used to change the visible semantics of a program, so what you see is not what you get. Most people agree that using AOP to add monitoring or logging to a program is an excellent fit (with the usual warning to beware of performance impact). This article shows how this can be done cleanly and transparently. It provides one good answer to a question that often arises about using JMX technology: how do you link the application's objects to the JMX instrumentation without breaking modularity? You don't want to hardwire JMX API references into application classes, and you don't want your JMX MBeans to be reaching into the innards of your application to pick out the objects they need. (There are other good answers too, by the way.)

Having said all that, I did have a few issues with the article. There are some minor inaccuracies in the code extracts, though I dare say that can easily be fixed. The advice to use Model MBeans rather than Standard MBeans, because of inheritance problems with the latter, seems to ignore the class javax.management.StandardMBean. I find that most cases where you might want to use Dynamic MBeans (of which Model MBeans are a kind) can more simply be coded using this class or a custom subclass.

The advice about ignoring thread safety is somewhat dangerous. While it is true that concurrent updates to statistics are typically rare, the Java Memory Model basically allows a thread to hold on to its private copy of a field for as long as it likes provided there's no synchronization. So with an aggressively-optimizing system you could find that each thread was maintaining its own copy of a supposedly-common set of statistics. The values you would observe would be essentially random. If you don't want to pay the penalty of synchronizing across a read-modify-write (like counter++ or whatever), but you also don't want to run the risk of the random behaviour I just mentioned, then declaring fields volatile is a good compromise. This can still give wrong results in the face of two concurrent read-modify-writes but as Ron says this is likely to be too rare to make any significant difference to the statistics.

Anyway, Ron finishes this Part 1 with this striking screenshot where the humble JConsole is used to present some very useful information. I'll be looking forward to Part 2!

JConsole screenshot showing Glassbox instrumentation

Adding Descriptors to MBeans in Mustang

Posted by emcmanus on October 22, 2005 at 09:41 AM | Permalink | Comments (3)

Descriptors allow you to give additional information about MBeans to management clients. For example, a Descriptor on an MBean attribute might say what units it is measured in, or what its minimum and maximum possible values are. As of Mustang (Java SE 6), Descriptors are a basic part of the JMX API and are available in all types of MBeans. Here's the easiest way to use them.

Mustang makes it very convenient to add information to an MBean. You can use annotations in a Standard MBean to define the Descriptor contents. For example, with this definition...

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Units {
    @DescriptorKey("units")
    String value();
}

...you can define an annotation @Units that you can then use like this...

public interface CacheMBean {
    @Units("whatsits")
    public int getUsed();
}

You can just cut-and-paste the @-infested text that defines @Units from the DescriptorKey documentation, so you don't need to remember all the details. Of course, as soon as you've defined @Units once you can use it in any number of MBeans.

As usual with Standard MBeans, you can make an MBean by defining a class Cache that implements CacheMBean and registering it in the MBean Server something like this...

MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example.domain:type=Cache,name=\"Whatever\"");
Cache cache = ...whatever...;
mbeanServer.registerMBean(name, cache);

Now you can see the units of the Used attribute defined by the getUsed() method in the interface...

MBeanInfo mbeanInfo = mbeanServer.getMBeanInfo(name);
for (MBeanAttributeInfo a : mbeanInfo.getAttributes()) {
    Descriptor d = a.getDescriptor();
    System.out.println("Attribute " + a.getName() + " has units " +
		       d.getFieldValue("units"));
}

...and as expected this will print...

Attribute Used has units whatsits

If the Descriptor doesn't contain a value for "units", then the getFieldValue() method will return null. The MBeanAttributeInfo.getDescriptor() method never returns null, though it might return an empty Descriptor.

You can imagine that a management console such as jconsole might use this kind of code to add a label to a graph of the Used attribute. The as-yet fanciful picture here shows the units, minValue, and maxValue items that have been added to the Descriptor for Used, and the graph that a console might produce of the Used value over time. The label of the graph and the minimum and maximum values come from the Descriptor items.

Graph of Used attribute with labels from Descriptor contents

This picture comes from my session at this year's JavaOne. Sessions are now online for free!

Coming soon: retrofitting Descriptors into Standard MBeans in Tiger.



Mustang JDK now includes attach-on-demand

Posted by emcmanus on September 29, 2005 at 09:32 AM | Permalink | Comments (4)

The Tiger JDK introduced a nifty feature whereby you could run an application with -Dcom.sun.management.jmxremote and then later connect to it using the jconsole tool. That allows you to see the JVM's instrumentation (memory, classes, threads) plus any JMX instrumentation you've defined yourself. As Alan Bateman describes, with the Mustang JDK you can now attach jconsole to any application, even if it wasn't launched with the magic -Dcom.sun.management.jmxremote incantation.

This is excellent news, for a few reasons. First of all, what a bummer if you suddenly realize after your uninterruptible app has been running for five days that you really want to get at its instrumentation, but damn, you forgot to incant -Dcom.sun.management.jmxremote! Not a problem any more. You can connect to any of your JVM processes from a jconsole on the same machine. (You can't connect to anyone else's processes, and you can't connect remotely in this way.)

Secondly, there's a small penalty in start-up time and in footprint when you launch with the incantation. On the old slow workstation I'm typing this on, this is almost three seconds and 500K. This isn't enormous, but it's not negligible either. So why not wait to pay the penalty until you actually need to, which might be never?

And finally, enabling this connection, even from the local machine, means creating and listening on a TCP/IP socket. If you're not going to be using it then why bother?

So the new feature is a big plus! If you want to play with it, you can download the latest Mustang snapshot at http://download.java.net/jdk6/binaries/. Both jconsole and the target app must be on Mustang.

By the way, Alan modestly doesn't mention the deep technical wizardry he needed to do to get this to work. Causing a target process to execute code for you (to create the JMX connector server) isn't a piece of cake!



Why aren't MXBeans OpenMBeans?

Posted by emcmanus on September 16, 2005 at 07:08 AM | Permalink | Comments (10)

In a comment on my last entry, rgreig asks:

One thing that struck me about MXBeans is that they are really fusion of standard MBeans and OpenMBeans, since they only use standard types. However they don't actually conform to OpenMBean conventions.

Why was the decision taken not to make MXBeans OpenMBeans? (i.e. return an OpenMBeanInfo from getMBeanInfo())

Therein lies a tale!

MXBeans really are OpenMBeans. But as you note they don't return OpenMBeanInfo. However, in Mustang, all the same information that would have been in the OpenMBeanInfo is present via Descriptors.

Instead of...

MBeanInfo mbi = mbeanServer.getMBeanInfo(objectName);
MBeanAttributeInfo mbai = mbi.getAttributes()[0];
OpenMBeanAttributeInfo ombai = (OpenMBeanAttributeInfo) mbai;
OpenType ot = ombai.getOpenType();

...you can use...

MBeanInfo mbi = mbeanServer.getMBeanInfo(objectName);
MBeanAttributeInfo mbai = mbi.getAttributes()[0];
Descriptor d = mbai.getDescriptor();
OpenType ot = (OpenType) d.getFieldValue("openType");

This fusion of OpenMBeanInfo functionality into plain MBeanInfo means that you can have OpenModelMBeans and other strange beasts.

Nevertheless, we did originally plan for MXBeans to return OpenMBeanInfo. The reason they don't is subtle.

In the original incarnation of MXBeans, in java.lang.management, we wanted to use the type long[] in the ThreadMXBean. But OpenTypes didn't support arrays of primitive types - they would only have supported Long[], substantially less efficient. So we avoided using OpenMBeanInfo in Tiger with the intent of fixing this problem in Mustang.

It now is possible to have an array of primitive type as an OpenType, so we could now describe the ThreadMXBean with an OpenMBeanInfo. However, there are some interoperability concerns that we didn't foresee.

Suppose you have a Tiger client, say jconsole running on Tiger, talking to a Mustang server. Since long[] didn't exist as an OpenType in Tiger, if we sent an OpenMBeanParameterInfo with type long[] to a Tiger, it will see it as if its type were Long[]. Suppose it lets the user call a method like
ThreadMXBean.getThreadInfo(long[] ids)

JConsole proposing ThreadMXBean operations

If jconsole saw an OpenMBeanParameterInfo for a Long[] then it would expect the signature array in MBeanServerConnection.invoke to contain Long[].class.getName(), i.e. "[Ljava.lang.Long;". But since the parameter is really a long[], it should be long[].class.getName(), i.e. "[J". If you pass the wrong signature, the method invocation will fail.

We could have envisaged various hacks to work around this problem, but we decided it would be simpler to continue to use MBeanParameterInfo rather than OpenMBeanParameterInfo, with the Descriptor containing the OpenType. In the example at hand, we'll have an MBeanParameterInfo where getDescriptor().getFieldValue("openType") returns ArrayType.getPrimitiveArrayType(long[].class). On Tiger, there's no such OpenType, but there's no Descriptor in MBeanParameterInfo either so the inconsistency evaporates. The Tiger client sees just the MBeanParameterInfo.getType(), which is "[J" as required.

For what it's worth, our implementation does use an OpenMBeanParameterInfo when it doesn't contradict the constraints I mentioned. In particular, if your attribute or parameter is a CompositeData then even a Tiger client will be able to see the corresponding CompositeType using OpenMBeanParameterInfo.getOpenType().



Optimizing the internals of the MBean Server

Posted by emcmanus on September 14, 2005 at 01:12 PM | Permalink | Comments (3)

Summer is of course the time when people take their vacation, and nowhere more so than here in France. You could be forgiven for thinking that the entire country grinds to a halt between the traditional vacation boundaries of the 14th of July (Bastille Day) and the 15th of August (Feast of the Assumption, a public holiday, don't ask). It seems like three quarters of high-street shops are closed for business. More to the point, three quarters of my co-workers are also on vacation, so, if I'm not, then the amount of time I spend in discussion and co-ordination is drastically reduced.

This summer I had a period of about two weeks like that where I could just lower my head and code. And that was a good thing, because there was something that really needed to be done.

The MBean Server is the core of the JMX API, and its implementation in the JDK includes code that dates from the very earliest release of that API, and indeed its proprietary predecessors. That means it's had six years or more to accumulate bug-fixes, interesting ideas that didn't quite work out, new features that were grafted on as best we could, and so on.

The last straw for me was the addition of MXBeans to the JMX API. MXBeans were initially implemented as a standalone package that used only the public JMX API. When the MXBean feature was added to Mustang, we just did the minimal adaptation work to make it work. It was still operating as a standalone package, taking no advantage of the implementation classes in the rest of the JMX API. The idea was to get the feature in place quickly, then revisit it later to clean up.

If you're like me, you're extremely sceptical about things that "we'll clean up later". Somehow, if it works, it never does get cleaned up. There's always something more urgent to do. I could see this coming a mile off for MXBeans.

This was bad for a number of reasons. MXBeans and Standard MBeans have a great deal in common. In fact you could consider that Standard MBeans are just MXBeans where the type mapping is the identity. So the fact that they shared almost no code meant that there was a lot of functionality implemented twice. Bug-fixes applied to one wouldn't automatically apply to the other. New features, such as annotations for descriptor contents would have to be implemented separately for each one. And optimizations in one wouldn't appear in the other.

This was exactly the situation we were in during the French shutdown. Standard MBeans had lots of caching logic so that the same MBeanInfo instance could be shared between all MBeans of the same type, and only computed for the first of them. MXBeans didn't have that, but they did cache Method objects so they didn't have to be retrieved again for every getAttribute or invoke on the MBean.

So, out with the hatchet. Refactor the logic for Standard MBeans and MXBeans so that they are just two concrete subclasses of an abstract MBean class. Put the caching of MBeanInfo objects and Methods into this class. Use the Visitor Pattern so the same introspection logic can construct MBeanInfo, method cache, and proxy data.

In this sort of environment, you have to pay lots of attention to WeakReferences so that all the cached information goes away when it's no longer used. It's really easy to set things up so that if you register an MBean from some class loader and then unregister it again, the class loader object is still referenced and can never be garbage collected.

While I had the hatchet out, I changed the way MBeans are handled so that every MBean is ultimately a DynamicMBean. Standard MBeans and MXBeans get wrapped in a DynamicMBean. The previous logic had separate handlers for Dynamic MBeans and Standard MBeans, and that tended to produce gratuitous inconsistencies between the two.

The intent of all these changes is to simplify the code, so future evolution will be easier; to reduce per-MBean memory usage; and to speed up MBean operations. The first of these is hard to measure but the measurements I've made on the other two are very encouraging. These changes will appear in build 53 of Mustang, which should be available on java.net on about the 23rd of September.



Compiling the JMX API in Mustang

Posted by emcmanus on August 30, 2005 at 09:10 AM | Permalink | Comments (2)

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.

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 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 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 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 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 ( RMIServer and RMIConnection), then for the JMX Remote API to work you'll need to generate the stubs yourself.

    You could add some <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.



November 2005
Sun Mon Tue Wed Thu Fri Sat
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      


Search this blog:
  

Archives

November 2005
October 2005
September 2005
August 2005
July 2005
June 2005

Recent Entries

JMX technology and NetBeans

Excellent article by Ron Bodkin about using AspectJ and JMX technologies for monitoring

Adding Descriptors to MBeans in Mustang



Powered by
Movable Type 3.01D


 XML java.net RSS