歡迎您光臨本站 註冊首頁

如何動態打開verbose class

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

  在一個Java企業環境中,可能會存在這樣那樣和類相關的情況,比如類衝突(classloader載入的類不是我們所需要的),perm gen內存泄漏等.出現這樣的情況,我們可能需要打開verbose class來trace class的load、unload情況.通過打開verbose class的格式如下:

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

  上述這種方法需要我們重新啟動伺服器,比如Tomcat、Weblogic等.但如果我們運行的是一個生產系統,重啟不是個好的方法.那麼除了上述方法,我們能否在不重啟伺服器的情況下動態打開、關閉verbose class呢?

  JDK的MBean為我們提供了這樣的介面,我們可以通過這樣的MBean來實現上述需求.MBean提供了大量JVM管理的介面,比如Memory、GarbageCollector、ClassLoading、Thread、Runtime等,更詳細的信息可以參考javax.management的API.下面我們看看如果通過程序的方式attach上target JVM,然後打開verbose class.

  對於attach到target jvm我們可以使用如下兩種方式:

  1:根據process id,即pid

  如何獲取pid呢?

  Windows: netstat -abn | find "7001", 7001是伺服器的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及listening port

  為了啟用remote managed port,我們需要在伺服器的啟動腳本中加入如下內容,如果你覺得不做驗證、non-ssl很不爽,你可以使用SSL及password file做認證.

  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后,說明我們已經attach到target JVM了,有了這個連接,我們可以為所欲為了,誇張了點哈.下面以classloading mbean為例,看看我們如何操作這樣的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 loadingunloading相關的信息了,如下:

  [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:beasyswls1030JDK160~1jrelibrt.jar]

  有了這些信息,我們就可以根據他們診斷類衝突之類的問題.如果需要關閉verbose class,直接在上面的程序中調用setVerbose(false)就可以了.


[火星人 ] 如何動態打開verbose class已經有486次圍觀

http://coctec.com/docs/java/show-post-60988.html