Tuesday, April 21, 2009

Detect Local Processes for JMX access

     People who dealt JMX must know about jconsole -- a very useful JMX-compliant monitoring tool. So when I was asked to create a web application that monitors JMX enabled remote servers, I tried to mimic the same functionalities that jconsole offers. One thing in particular, is that how jconsole detects local processes that are available for viewing.

     First of all, jconsole from Java5 and Java6 has different behavior on detection. Java5 only lists local processes that are JMX enabled while Java6 lists all local processes and greys out the ones that is not available for viewing and has the ability to enable JMX agent on a process that can be viewed.

     I think this is because of the attach API introduced in Java6. By using the VirtualMachine class from attach API, I'm able to tell whether a process is running under Java6. As long as a process is running using Java6, VirtualMachine can load an agent to it and thus enable the JMX viewing in jconsole. Knowing where the difference comes from, I created a simple class to mimic the very same function using attach API in conjunction with jps runtime command.


package net.katiewang.jmx.local;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import sun.tools.jps.Jps;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

/**
 * @author KWang
 *
 */
public class DetectLocalProcess {

   protected static enum STATUS{enabled, notEnalbed, willBeEnabled};

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        // first round: get all process info.
        // process id is the key, name of the process is the value
        // name includes full package name for the application's main class
        // or the full path name to the application's JAR file
        // along with the arguments passed to the main method
        Map processes = getProcesses();

        // second round: detect if jmx is enabled
        // process id is the key, whether the process is jmx enabled is the
        // value
        Map jmx = detectJMXAgent(processes.keySet());

        printProcessInfo(processes, jmx);
    }

    private static void printProcessInfo(Map processes, Map jmx){
        for(Map.Entry process : jmx.entrySet()){
        System.out.println("******************************");
        System.out.println("PID: " + process.getKey());
        System.out.println("Name: " + processes.get(process.getKey()));
        System.out.println("Status: " + getString(process.getValue()));
        }
    }

    private static String getString(STATUS value) {
        switch (value) {
            case enabled:
                return "Enabled";
            case willBeEnabled:
                return "Will Be Enabled";
            case notEnalbed:
            default:
                return "Not Enabled";
        }
        }

    private static Map detectJMXAgent(Set processids) throws IOException {
        Map jmx = new TreeMap();

        Runtime rt = Runtime.getRuntime();

        BufferedReader br = new BufferedReader(new InputStreamReader(rt.exec("jps -l -v")
            .getInputStream()));
        String line = new String();
        while ((line = br.readLine()) != null) {
            String[] proc = line.split(" ");
            if (processids.contains(proc[0])){
                STATUS isJmx = STATUS.notEnalbed;
                for(String process : proc){
                    if(process.startsWith("-Dcom.sun.management.jmxremote") ||
                        process.startsWith("-Dcom.sun.management.config.file")){
                        isJmx = STATUS.enabled;
                        break;
                    }
                }
                if(!STATUS.enabled.equals(isJmx)){
                    try {
                        VirtualMachine.attach(proc[0]);
                        isJmx = STATUS.willBeEnabled;
                    } catch (AttachNotSupportedException e) {
                        //do nothing
                    }
                }
                jmx.put(proc[0], isJmx);
            }
        }
        return jmx;
    }

    private static Map getProcesses() throws IOException {
        Map processes = new TreeMap();
        Runtime rt = Runtime.getRuntime();

        BufferedReader br = new BufferedReader(new InputStreamReader(rt.exec(
            "jps -l -m").getInputStream()));
        String line = new String();
        while ((line = br.readLine()) != null) {
            String[] proc = line.split(" ");
            if (proc[1].equals(Jps.class.getName())
                || proc[1].equals(DetectLocalProcess.class.getName()))
                continue; // ignore jps command process and this process

            processes.put(proc[0], line.substring(proc[0].length()).trim());
        }
        return processes;
    }

}


     The result will be something like:

******************************
PID: 2476
Name: org.apache.catalina.startup.Bootstrap start
Status: Not Enabled
******************************
PID: 3872
Name: my_jmx_enabled_app.jar client
Status: Enabled
******************************
PID: 5164
Name: sun.tools.jconsole.JConsole
Status: Will Be Enabled


     With viewable process dectected. Now I can simply using the attach API to create a JMX monitoring service connection.

     Attach API is not included in Java classpath by default. So when running my little test class, you need to either make sure to include tools.jar in your classpath or comment out the if statement which calls VirtualMachine.attach(String processId) method (Of course, in this case, you'll only know processes that are JMX enable at start -- same behavior as jconsole in Java5).

Sunday, March 15, 2009

An Example of Culture Difference between China and US

When I was in fourth or fifth grade, my teacher Miss Wang once told us that while she was an intern at another school, there was this student whose parents were doctors studied overseas and the student didn't wear the same cloth for two weeks. At that time, my only though is (and I think most of my classmates have the same though) that the student's family must be really rich cause I was used to wear same set of clothing for almost a week during winter time. And even I change cloth everyday during summer, there is no way I can wear different set everyday for two weeks. It wasn't till I came to US that I realized I was totally wrong.




In China, it is very common to see airer (I couldn't come up with a better name for it.) outside a balcony. That is because unlike Americans who use washing machine and dryer to clean their cloth, Chinese way of cleaning is still very traditional -- hand wash and natural drying by direct sunshine. Even there are cleaning services, they are usually only targeting hotels, not common families. Besides, Chinese people prefers the smell of the sun. Imaging hand washing your own or even your whole family's cloth by hand everyday, I believe no American would love to do that. Even though nowadays washing machine are common in big cities, people are still used to hand wash their delicates cause they believe washing machine will shorten the life of these cloth. On the other side, I once heard this funny story about Chinese farmers use washing machine to clean fresh potatoes and causing their washing machine to jam because of the high soil level.

Now that I'm in America, I realized that people will think you are not sanitary if you wear the same cloth several days in a row. I start to adapt to the culture difference and try not to wear same cloth for more than two days. But the truth is that I sweat less than I was in China because Chinese don't turn on AC at home except extreme weather. And not all schools and/or workplace are equipped with AC. Not to mention there is no strict smoking-free area in most places in China. My cloth is more likely to catch some weird smell in China than in America. And, no wonder the student didn't wear same cloth for two weeks. I have to wait about a month before I can wash my "dirty" cloth in two loads - one for colored and the other for whites.

Ever since the foreign businesses start to expand to China, the young Chinese generation starts to change too. My aunt once complained to me that my cousin who works for a Japanese company tends to change cloth everyday and leaves the cleaning job to her. But there lies differeces. First of all, my aunt doesn't have a washing machine. Second of all, my cousin doesn't have a lot cloth to change to. So his clothings are washed more frequently which means they are going to be wasted far more quickly than they can be.

This got me thinking. China is the biggest developing country in the world. By introducing foreign businesses into the country, we can learn advanced technologies faster and develop China quicker than ever. But that doesn't mean we should adapt everything blindly. Every country has it's own culture and conditions which makes the country unique, different from others. While learning from others, we should filter out or at least being flexible to the ones that doesn't fit China's culture and conditions. Blind learning can sometime do no good to a country and maybe even destroy a country's good assets. In this case, using washing machine is a more effecient way to clean clothes, especially in big cities with fast pace. Changing clothing on a frequent basis is better for one's healty. But if my cousin doesn't have a washing machine and he doesn't wash his own cloth, he shouldn't force into changing clothing on a daily basis and leaves all the burden to my aunt, which in Chinese traditional view is a disrespect to the elderly.

I think America is a good example of culture fusion. The country has only about couple hundred years of history. But because it's special condition -- combines people/elites from all over the world into one, it is able to develop into one of the strongest countries in the world in such a short time. However, I wouldn't say America is a good example for China. Unlike America, China has one of the most ancient history. Like a thousand-year-old tree, its root goes much more deeper than it looks. It takes more time than others to bring new blood into its stream. But once the new blood runs smoothly in the stream, it will be much stronger than others. In this case, washing machine is the new blood, even though it's more efficient, Chinese people still prefer to wash their cloth by hand. But with the faster pace of living in the modern world, I believe sooner or later the younger generation will switch their preferences to washing machine which can result a better use of time. And on the other side, I don't want America to be an example for China. Behind it's success, America is also called a culture destroyer. Study shows that it's very likely that within no more than four generations, off-springs of immigration families will forget their first language and, more to that, their roots. I hope China can keep it's positive culture and conditions during any transition.

No matter where I am, no matter where I go, my skin color tells everyone I'm a Chinese. And, no matter what happens, I'll always say that I'm proud to be a Chinese. I don't want to deny the facts that China's government has it's flaws. I believe every country's government has flaws. It's just a matter of how many. But I came to US for a better understanding of my own country. And by doing so, I hope one day I can help my country to grow stronger, even if just a little bit. My best wishes to China's future!