 |
Eamonn McManus's Blog
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!
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.
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)
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

|