posts - 42,comments - 83,trackbacks - 0
                  在一個(gè)Java企業(yè)環(huán)境中,可能會(huì)存在這樣那樣和類相關(guān)的情況,比如類沖突(classloader加載的類不是我們所需要的),perm gen內(nèi)存泄漏等。出現(xiàn)這樣的情況,我們可能需要打開verbose class來(lái)trace class的load、unload情況。通過(guò)打開verbose class的格式如下:

          java %JAVA_OPTIONS% %MEM_ARGS%  -verbose:class MainClass >tmp.out 2>&1

                  上述這種方法需要我們重新啟動(dòng)服務(wù)器,比如Tomcat、Weblogic等。但如果我們運(yùn)行的是一個(gè)生產(chǎn)系統(tǒng),重啟不是個(gè)好的方法。那么除了上述方法,我們能否在不重啟服務(wù)器的情況下動(dòng)態(tài)打開、關(guān)閉verbose class呢?

                   JDK的MBean為我們提供了這樣的接口,我們可以通過(guò)這樣的MBean來(lái)實(shí)現(xiàn)上述需求。MBean提供了大量JVM管理的接口,比如Memory、GarbageCollector、ClassLoading、Thread、Runtime等,更詳細(xì)的信息可以參考javax.management的API。下面我們看看如果通過(guò)程序的方式attach上target JVM,然后打開verbose class。

                     對(duì)于attach到target jvm我們可以使用如下兩種方式:
          1:根據(jù)process id,即pid
          如何獲取pid呢?
          Windows: netstat -abn | find "7001", 7001是服務(wù)器的listening port
          Linux/Unix: ps -ef | grep java

           1 public MBeanServerConnection getMBeanServerConnection(long pid)
           2 {
           3     MBeanServerConnection serviceConnection = null;
           4     VirtualMachine vm = null;
           5     try
           6     {
           7         vm = VirtualMachine.attach(String.valueOf(pid));
           8         String connectorAddress =
           9             vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
          10         if (connectorAddress == null) {
          11             String agent = vm.getSystemProperties().getProperty("java.home"+
          12                     File.separator + "lib" + File.separator + "management-agent.jar";
          13             vm.loadAgent(agent);
          14             connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
          15         }
          16         if(connectorAddress == null)
          17             System.exit(1);
          18         serviceConnection = getMBeanServerConnection(connectorAddress);
          19     }catch(Exception e){}
          20     return serviceConnection;
          21 }

          2:remote management的listening address及l(fā)istening port
          為了啟用remote managed port,我們需要在服務(wù)器的啟動(dòng)腳本中加入如下內(nèi)容,如果你覺得不做驗(yàn)證、non-ssl很不爽,你可以使用SSL及password file做認(rèn)證,具體可以參考:http://www.j2ee.me/j2se/1.5.0/docs/guide/management/agent.html
          set JAVA_OPTIONS=-Dcom.sun.management.jmxremote.port=9192 %JAVA_OPTIONS%
          set JAVA_OPTIONS=-Dcom.sun.management.jmxremote.authenticate=false %JAVA_OPTIONS%
          set JAVA_OPTIONS=-Dcom.sun.management.jmxremote.ssl=false %JAVA_OPTIONS%

           1 public MBeanServerConnection getMBeanServerConnection(String hostname, String listeningPort)
           2 {
           3     MBeanServerConnection conn = null;
           4     try{
           5         url = "service:jmx:rmi:///jndi/rmi://"+host+":"+port+"/jmxrmi";
           6         JMXServiceURL serviceURL = new JMXServiceURL(url);
           7         connector = JMXConnectorFactory.connect(serviceURL);
           8         conn = connector.getMBeanServerConnection();
           9     }catch(Exception e){
          10         e.printStackTrace();
          11     }
          12     return conn;
          13 }

                  好了,我們拿到MBeanServerConnection后,說(shuō)明我們已經(jīng)attach到target JVM了,有了這個(gè)連接,我們可以為所欲為了,夸張了點(diǎn)哈。下面以classloading mbean為例,看看我們?nèi)绾尾僮鬟@樣的MBean,如果從這些MBean信息,

           1     private void checkClassLoadingInfo(MBeanServerConnection conn)
           2     {
           3         try
           4         {
           5             clMBean = (ClassLoadingMXBean)ManagementFactory.
           6                 newPlatformMXBeanProxy(conn, ManagementFactory.CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class);
           7         }catch(IOException ioe){}
           8         System.out.println(clMBean.getTotalLoadedClassCount());
           9         System.out.println(clMBean.getLoadedClassCount());
          10         System.out.println(clMBean.getUnloadedClassCount());
          11         //here we can turn on verbose of class loading dynamically
          12         clMBean.setVerbose(true);
          13     }

                  打開verbose class后,我們就可以看到class loading\unloading相關(guān)的信息了,如下:
          [Loaded weblogic.servlet.FileServlet from file:/D:/beasys/wls1030/wlserver_10.3/server/lib/weblogic.jar]
          [Loaded weblogic.utils.string.CachingDateFormat$ParseCacheHolder from file:/D:/beasys/wls1030/modules/com.bea.core.utils_1.4.0.0.jar]
          [Loaded java.lang.StringIndexOutOfBoundsException from d:\beasys\wls1030\JDK160~1\jre\lib\rt.jar]

                  有了這些信息,我們就可以根據(jù)他們?cè)\斷類沖突之類的問題。如果需要關(guān)閉verbose class,直接在上面的程序中調(diào)用setVerbose(false)就可以了。

                  正如前面所說(shuō)的那樣,這樣的Mbean有很多,具體的需要你參考JDK的management API。
          posted on 2009-09-08 09:46 走走停停又三年 閱讀(2932) 評(píng)論(0)  編輯  收藏 所屬分類: Java Technology
          主站蜘蛛池模板: 元谋县| 疏勒县| 西和县| 含山县| 马山县| 明星| 靖西县| 额尔古纳市| 呼伦贝尔市| 西充县| 察哈| 襄城县| 靖西县| 中山市| 鸡泽县| 望都县| 漠河县| 吉水县| 陵川县| 濉溪县| 朝阳区| 周至县| 云南省| 揭阳市| 兖州市| 彰武县| 屏边| 团风县| 商都县| 额敏县| 驻马店市| 二手房| 南昌县| 金阳县| 山西省| 莲花县| 郎溪县| 桂阳县| 中江县| 广东省| 浦北县|