Blog Control to Major Tom.
"there's still lofty dreams, meager desires, still silliness."
SPONSORED BY:
  Your Company Here  
Inquire Within

Another Java Options Submission

I recently got a message from Oliver F. regarding an option he found in a bug, Bug 5108893 which has to do with some performance problems with Math.abs() on various x86 platforms. Within the bug report, he found the option -XX:UseSSE=i which apparently forces the Hotspot compiler to use different SSE instructions for various mathematical operations.

Oliver didn't explain why he was looking into the bug, but at any rate, I have added it to the Options List.


(2004-12-13 17:41:32.0) Comments [1] // Permalink

Another Update to the Options List

I received a mail from Martin S. regarding a problem he was having trying to prevent full GCs from occuring because of collection of the permenant generation. As he states it:

My goal of course is to avoid Full GC cycles triggered by the permanent generation, or even good diagnosis of what's going on would help a lot since in our server application we have not been able to isolate the cause of that yet.

He thought that the use of -XX:+CMSPermGenSweepingEnabled should have done it, but noticed no change. Well, unfortunately I was of no help, but he managed to figure out the trick himself and dropped a note with his findings:

The trick was to combine -XX:+CMSPermGenSweepingEnabled [and] -XX:+CMSClassUnloadingEnabled. On its own, CMSPermGenSweepingEnabled doesn't seem to take effect.

I have updated the Options List to reflect this.

Thanks Martin!.


(2004-11-18 11:07:19.0) // Permalink

Reflection solves a JMX problem.

One of the cool things in the Java Platform I've always liked is the introspection and reflection capabilities. Although Java is surely not the first to provide this, it is quite a step up from using say, dlopen() and dlsym() in C code for example.

These features recently help me elegantly solve a problem I had with JMX. I have been looking at instrumenting the code that is used serve many of the www.sun.com web pages, in order to give us better information on how the system is performing.

The Java Management Extensions (JMX) provide a pretty straight forward way to enable management and instrumention in your applications. But here's the problem I was having.

The easiest way to use JMX is to use Standard MBeans. This is done by creating an bean interface class which you then implement in your code. The interface defines getter and setter methods for data points you want to monitor and/or change. JMX, itself, then uses introspection to find and use the MBean interface. Here's an example:

public interface DispatcherMBean {

	public int getRequestsProcessedCount();

	public void setCacheSize(int cacheSize);
}

public class Dispatcher implements DispatcherMBean {

	public int getRequestsProcessedCount() {
		return statRequestsProcessedCount;
	}

	public void setCacheSize(int cacheSize) {
		this.maxCacheSize = cacheSize;
	}

        /*
         * ...
	 */
}

Now to register the object with the MBeanServer its only a few simple method calls:

	ObjectName dispatcherName = null;
	dispatcherName = new ObjectName("Domain:name=Dispatcher");
	server.registerMBean(this, dispatcherName);

This all works great. Very straightforward. Very simple. The only problem is that although JMX provides the ability to tie descriptions to each attribute, the Standard MBean used this way doesn't provide the ability to create them. Having descriptions available would definitely be helpful when working in a Management Console trying to figure out what each attribute means.

So this is the problem I was trying to solve in the first place. How to easily maintain descriptions for the JMX attributes I was creating.

First, I looked into the other JMX MBeans. The Dynamic MBean, for example, provides alot more flexibility, including creating descriptions, but that flexibility comes at a cost. There is alot more code involved in instrumenting your code with Dynamic MBeans. You have maintain a lot of different structures like MBeanAttributeInfo, MBeanOperationInfo, MBeanConstructorInfo, etc.. You also have more generalized methods that you implement like getAttribute() and setAttribute(). The code becomes quite long, an example that comes with JMX is SimpleDynamic.java

So I decided that was out.

As I was trying out different JMX implementations, I noticed in the MX4J documentation that they provide an extension in MX4J for maintaining descriptions with Standard MBeans. The documentation says that this extension is "Totally transparent with respect to MBeans portability across JMX implementations." owever, the solution relies on a couple of MX4J-specific classes. Without them, your code would not compile, so in essence you are tied to MX4J. I strive to stay free from specific implementations so I decide this extension was out.

So as I searched around a little bit more, I found that there is an alternate way to create a Standard MBean which provides some customization hooks including the ability to maintain descriptions for attributes. Its done by using the base class StandardMBean. And the specific method that I was interested in was:

	public String getDescription(MBeanAttributeInfo info);

Ok, so I had to first restructure my code to extend StandardMBean, which has its own problems because much of our code already extends other classes. But I managed to come up with a peer class framework. The peer class is given access to protected fields for management, this ends up being a bit of a plus to have the management functions separated out.

Now the only problem is how to easily manage descriptions and how to implement getDescription(). One obvious thought is to create a Map of some sort or a Properties file ResourceBundle and initialize it with all the attribute names and descriptions. I started going down that route but it just seemed clunky.

As I looked back, and thought about how JMX uses reflection, I realized I could use reflection myself to easily accomplish this. What I figured I could do is come up with some sort of naming scheme to some internal String fields which I could programmatically search for and get the values of. And that's exactly what I did.

All that I do is create public static String fields that are named the same as the attributes with the additional suffix of Desc. And then I created a getDescription() method that takes the name of the attribute passed in, tacks on "Desc" to the end, and then uses Class.getField() to search for it.

My original example, modified this way looks like this:

public interface DispatcherMBean {
	public int getRequestsProcessedCount();

	public void setCacheSize(int cacheSize);
}

public class DispatcherMBeanImpl extends StandardMBean 
	implements DispatcherMBean {


	public DispatchMBeanImpl(Dispatcher dispatcher) {
		this.dispatcher = dispatcher;
	}

	public static String = 
		"Contains the total number of requests processed";

	public int getRequestsProcessedCount() {
		return dispatcher.statRequestsProcessedCount;
	}

	public static String =
		"The cache size, in megabytes.";

	public void setCacheSize(int cacheSize) {
		dispatcher.maxCacheSize = cacheSize;

	public String getDescription(MBeanAttributeInfo info) {
		try {
			Field field = getClass().getField(info.getName() + "Desc");
			return (String) field.get(this);
		}
		catch (Exception e) {
			e.printStackTrace();
			return info.getDescription();
		}
	}

       /*
        * ...
	*/
}
And to register the MBean, only a couple of simple lines still:
	DispatchMBeanImpl mbean = new DispatcherMBeanImpl(dispatcher);
	ObjectName dispatcherName = null;
	dispatcherName = new ObjectName("Domain:name=Dispatcher");
	server.registerMBean(mbean, dispatcherName);

And that's it. Pretty simple.


(2004-10-25 10:49:02.0) Comments [1] // Permalink

1st JVM Option List Community Find

I just posted a new version of the JVM Options List after receiving the first community submission from Simon T.

He was given the suggestion to use a -XX:+UseFastJNIAccessors option from Sun technical support as a workaround to a problem he was encountering with java2d.DrawPolygons in the new Tiger release of the JDK. Unfortunately, the option did not work for him, but at least the list is one better for it!


(2004-10-01 12:18:29.0) Comments [2] // Permalink

List of JVM Options

At the urging of a few folks that have found this useful, I have posted a list I have been maintaining of all the JVM Options I could find. The list includes descriptions and versions of the JVM the options are valid for. Hopefully this will be useful to other Java Platform developers out there. Apparently it has been useful inside Sun to others besides myself. Anyways, you can find the list at http://blogs.sun.com/roller/page/watt/JVMOptionsList. Enjoy.


(2004-09-17 17:47:15.0) Comments [7] // Permalink

A Few of My Favorite JVM Options

I've been responsible for serveral online systems at Sun over the years. Systems that are meant to have a 99.9+ up time. For the last several years these systems have been primarily Java based. As I have trudged over tuning problems with these systems, I have built up a small list of JVM options that have been very useful for me, and here they are.

-Xsqnopause - When you send the JVM a SIGQUIT, it normally suspends execution and presents a menu on the tty of several debugging options. This can be a bad thing while debugging an online system. For example, a web server like Tomcat, would just pause, and leave all the users hanging waiting for a response. What this option does is tell the JVM to simply output a thread dump and then continue executing. The thread dump can then later be analysed. Or, what's often useful when searching for deadlocks, is taking another thread dump at a later time, and comparing the two.

-XX:+JavaMonitorsInStackTrace - When debugging a particularly nasty problem one week where the JVM would seem to stop doing real work, I found that the normal thread dump output was insufficient to determine what was going on. After hours of scouring the net, I found this option, which provides monitor information in thread dumps. Monitors are the mechanism which provides synchronization, so on a hunch that it might be a deadlock, I decided to try it. After producing a few thread dumps with this option, it became clear that the it was not a deadlock issue but rather a starvation condition. Many threads were waiting for their turn, and spinning until they got it. More on this later.

-XX:+PrintGCDetails and -verbose:gc - These are both nearly the same thing, although PrintGCDetails is only available on 1.4.0 and newer JVMs. They both provide helpful displays of how garbage collection is occuring, and help you tune garbage collection appropriately for your application with the millions of other garbage collection options. Essentially they show how often and how long GCs are occuring. In older JVMs, during a GC, the JVM would have to pause all running threads, to do its thing, so making GCs happen less often and take a shorter amount of time is essential in an online system. Alot of work has been done on GCs and my understanding is that the garbage collectors in the newer JVMs can do much more work in parallel.

-XX:MaxNewSize - Out of those millions of other garbage collection options, this one I have found particularly useful. It sets the maximum size of the young, or new generation much higher than the default. Doing this is particularly useful with applications that create large amounts of temporary or short lived objects. If the new size isn't large enough, some of these objects have to be prematurely promoted to the the old generation, and which eventually will cause more full GCs to occur more frequently. Nip those objects in the bud if you can.

-XX:+UseLWPSynchronization - The starvation issue I mentioned earlier ended up being a problem with the threading model the JVM was using. The particular application I encountered this was on Solaris 8, in which the JVM defaulted to a many LWPs-to-many Threads model. The problem though was that the number of LWPs were only a fraction of the number of actual threads, and in order for a thread to run, it needed to be on an LWP. The JVM started spending all its time trying to schedule thread on LWPs. With the UseLWPSynchronization flag, The JVM changed the number of LWPs it created to match the number of threads, which made simplified scheduling. The JVM could essentially just let the kernel schedule LWPs to run on CPUs, without the intermediate step of scheduling threads on LWPs.


(2004-07-20 17:08:54.0) Comments [2] // Permalink


archives
links