如何本身監控java

使用JMXhtml

JAVA Management Extensions的縮寫,Java自帶的一種管理資源的技術,好比對Java 應用程序,系統和網絡等java

java自帶的獲取各類信息的工具類

java自帶的java.lang.management.ManagementFactory 能夠看到它提供的一些列方法:瀏覽器

能夠看到它提供了包括類加載、內存、線程等MXBean

以Memory爲例,它包括兩部分,MemoryMXBean和MemoryPoolMXBeanbash

/**
 * Returns the managed bean for the memory system of
 * the Java virtual machine.
 *
 * @return a {@link MemoryMXBean} object for the Java virtual machine.
 */
public static MemoryMXBean getMemoryMXBean() {
    return ManagementFactoryHelper.getMemoryMXBean();
}
複製代碼

MemoryMXBean提供獲取堆內存和非堆內存的方法,返回對象MemoryUsage相應包含最大、已使用等信息網絡

/**
 * Returns the current memory usage of the heap that
 * is used for object allocation.  The heap consists
 * of one or more memory pools.  The <tt>used</tt>
 * and <tt>committed</tt> size of the returned memory
 * usage is the sum of those values of all heap memory pools
 * whereas the <tt>init</tt> and <tt>max</tt> size of the
 * returned memory usage represents the setting of the heap
 * memory which may not be the sum of those of all heap
 * memory pools.
 * <p>
 * The amount of used memory in the returned memory usage
 * is the amount of memory occupied by both live objects
 * and garbage objects that have not been collected, if any.
 *
 * <p>
 * <b>MBeanServer access</b>:<br>
 * The mapped type of <tt>MemoryUsage</tt> is
 * <tt>CompositeData</tt> with attributes as specified in
 * {@link MemoryUsage#from MemoryUsage}.
 *
 * @return a {@link MemoryUsage} object representing
 * the heap memory usage.
 */
public MemoryUsage getHeapMemoryUsage();
/**
 * Returns the current memory usage of non-heap memory that
 * is used by the Java virtual machine.
 * The non-heap memory consists of one or more memory pools.
 * The <tt>used</tt> and <tt>committed</tt> size of the
 * returned memory usage is the sum of those values of
 * all non-heap memory pools whereas the <tt>init</tt>
 * and <tt>max</tt> size of the returned memory usage
 * represents the setting of the non-heap
 * memory which may not be the sum of those of all non-heap
 * memory pools.
 *
 * <p>
 * <b>MBeanServer access</b>:<br>
 * The mapped type of <tt>MemoryUsage</tt> is
 * <tt>CompositeData</tt> with attributes as specified in
 * {@link MemoryUsage#from MemoryUsage}.
 *
 * @return a {@link MemoryUsage} object representing
 * the non-heap memory usage.
 */
public MemoryUsage getNonHeapMemoryUsage();
複製代碼

MemoryPoolMXBean可以獲取 memory pool的名字,好比是不是Eden區,old區等等架構

/**
 * Returns a list of {@link MemoryPoolMXBean} objects in the
 * Java virtual machine.
 * The Java virtual machine can have one or more memory pools.
 * It may add or remove memory pools during execution.
 *
 * @return a list of <tt>MemoryPoolMXBean</tt> objects.
 *
 */
public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
    return ManagementFactoryHelper.getMemoryPoolMXBeans();
}
複製代碼

要獲取整個的內存大小,須要使用Runtimeoracle

/**
 * Returns the amount of free memory in the Java Virtual Machine.
 * Calling the
 * <code>gc</code> method may result in increasing the value returned
 * by <code>freeMemory.</code>
 *
 * @return  an approximation to the total amount of memory currently
 *          available for future allocated objects, measured in bytes.
 */
public native long freeMemory();

/**
 * Returns the total amount of memory in the Java virtual machine.
 * The value returned by this method may vary over time, depending on
 * the host environment.
 * <p>
 * Note that the amount of memory required to hold an object of any
 * given type may be implementation-dependent.
 *
 * @return  the total amount of memory currently available for current
 *          and future objects, measured in bytes.
 */
public native long totalMemory();

/**
 * Returns the maximum amount of memory that the Java virtual machine will
 * attempt to use.  If there is no inherent limit then the value {@link
 * java.lang.Long#MAX_VALUE} will be returned. </p>
 *
 * @return  the maximum amount of memory that the virtual machine will
 *          attempt to use, measured in bytes
 * @since 1.4
 */
public native long maxMemory();
複製代碼

獲取其它想要監控的信息

經過java.lang.management.ManagementFactory 獲取 MBeanServer,平臺全部的MBean都會註冊到這個上面。而後經過獲取ObjectName和屬性就能得到值app

JMX的架構

分紅3塊:Instrumentation,JMX agent和Remote managementdom

  • Instrumentation: 使用MBeans來實現資源檢測(resources' instrumentation),MBeans有一套標準的規範,實現MBeans必須遵循,以實現標準化的處理ide

  • JMX Agent: 用於直接的控制資源,並使得遠程管理應用可以獲取這些資源,它一般和控制的資源在同一臺機器上。JMX Agent的核心組件是MBean server[]MBeans註冊的地方]

  • Remote management: JMX Agent實現的不一樣協議適配器和connector使得註冊在MBean server上的MBeans都可以被看到,好比HTML的adaptor可以使得瀏覽器上可以展現MBean

MBean

一個MBean能夠表明一個設備,應用或者任何能夠被管理的資源。MBeans會暴漏具備以下特性的管理接口:

  • 可讀可寫的屬性集合:讀對應着 get開頭的方法,必須有返回值;寫對應着set開頭的方法

  • 可調用操做的集合:自定義的一下方法

  • 一段自個人描述

標準的MBeans

包含兩個部分:MBean的接口和它的實現類。命名接口爲 xxxMBean 。好比命名爲 PaxiMBean,而後用一個java類 Paxi來實現這個接口。

MBean

package main.jmx;
public interface PaxiMBean {
    void sayHi();
    String getName();
    void setName(String name);
}
複製代碼

Mbean實現

public class Paxi implements PaxiMBean {
    @Override
    public void sayHi() {
        System.out.println("hi");
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name=name;
    }
    private String name="paxi";
}
複製代碼

Agent例子

package main.jmx;
public class MyAgent {
    public static void main(String[] args) {
        //1:獲取平臺已經建立並初始化的MBeanServer,沒有就經過MBeanServerFactory.createMBeanServer()建立
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        try {
            //2:每一個MBean必須有一個object name,name遵守標準格式
            ObjectName name = new ObjectName("main.jmx:type=Paxi");
            Paxi paxi = new Paxi();
            //3:註冊MBean
            mbs.registerMBean(paxi,name);
            System.out.println("wait for incoming request");
            Thread.sleep(Long.MAX_VALUE);
        } catch (MalformedObjectNameException e) {
            e.printStackTrace();
        } catch (NotCompliantMBeanException e) {
            e.printStackTrace();
        } catch (InstanceAlreadyExistsException e) {
            e.printStackTrace();
        } catch (MBeanRegistrationException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
複製代碼

在命令行運行 jconsole,選中MBean,點擊左側欄 main.jmx

獲得操做界面
點擊sayHi,會彈窗提示調用成功

此時界面上會出現 sayHi的內容

wait for incoming request
hi
複製代碼

MXBeans

它是一種MBean的一種,僅用來引用一種預約義的數據類型。它的定義爲 方式能夠和MBean同樣。接口後綴爲MXBean而後在實現

public interface PaxiQMXBean {
    PaxiQueue getPaxiQueue();
    void clearQueue();
}
複製代碼

或者是使用MXBean的註解

@MXBean
public interface PaxiQInAnnotation {
    PaxiQueue getPaxiQueue();
    void clearQueue();
}
複製代碼

實現

public class PaxiQ implements PaxiQMXBean {
    private Queue<String> queue;

    public PaxiQ(Queue<String> queue) {
        this.queue = queue;
    }

    @Override
    public PaxiQueue getPaxiQueue() {
        synchronized (queue){
            return new PaxiQueue(new Date(),queue.size(),queue.peek());
        }
    }

    @Override
    public void clearQueue() {
        synchronized (queue){
            queue.clear();
        }
    }
}
複製代碼

其中的PaxiQueue是本身定義的一個對象

public class PaxiQueue {
    private final Date date;
    private final int size;
    private final String head;

    @ConstructorProperties({"date","size","head"})
    public PaxiQueue(Date date, int size, String head) {
        this.date = date;
        this.size = size;
        this.head = head;
    }

    public Date getDate() {
        return date;
    }

    public String getHead() {
        return head;
    }

    public int getSize() {
        return size;
    }
}
複製代碼

Agent的實現爲

public class MyAgent {
    public static void main(String[] args) {
        //1:獲取平臺已經建立並初始化的MBeanServer,沒有就經過MBeanServerFactory.createMBeanServer()建立
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        try {
            ObjectName name = new ObjectName("main.jmx:type=PaxiQ");
            Queue<String> queue = new ArrayBlockingQueue<String>(10);
            queue.add("r-1");
            queue.add("r-2");
            queue.add("r-3");
            PaxiQ mxbean = new PaxiQ(queue);
            //3:註冊MBean
            mbs.registerMBean(mxbean,name);
            System.out.println("wait for incoming request");
            Thread.sleep(Long.MAX_VALUE);
        } catch (MalformedObjectNameException e) {
            e.printStackTrace();
        } catch (NotCompliantMBeanException e) {
            e.printStackTrace();
        } catch (InstanceAlreadyExistsException e) {
            e.printStackTrace();
        } catch (MBeanRegistrationException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
複製代碼

啓動後運行jconsole

能夠看到自定義的屬性值爲CompositeDataSupport,雙擊它能夠看到等他的內容:

可是若是PaxiQMXBean是一個MBean,即名字是PaxiQMBean,這個時候經過jconsole是沒法找到的。

建立一個本身的JMX client

JMX client代碼

public class PaxiClient {
    public static void main(String[] args) {
        System.out.println("create RMI client");
        try {
            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
            JMXConnector jmxConnector = JMXConnectorFactory.connect(url, null);
            MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
            System.out.println("domains");
            String[] domains= mBeanServerConnection.getDomains();
            Arrays.sort(domains);
            for (String domain:domains){
                System.out.println(domain);
            }
            System.out.println("domain:"+mBeanServerConnection.getDefaultDomain());
            System.out.println("MBean count:"+mBeanServerConnection.getMBeanCount());
            Set<ObjectName> names = new TreeSet<ObjectName>(mBeanServerConnection.queryNames(null,null));
            for (ObjectName name:names){
                System.out.println("objectname:"+name);
            }
            ObjectName mbeanName = new ObjectName("main.jmx:type=Paxi");
            PaxiMBean mbeanProxy = JMX.newMBeanProxy(mBeanServerConnection,mbeanName,PaxiMBean.class,true);
            System.out.println("add notification listener..");
          // 自定義消息的監聽
            PaxiClientListener listener = new PaxiClientListener();
            mBeanServerConnection.addNotificationListener(mbeanName,listener,null,null);
            mbeanProxy.setName("new name");
            System.out.println("wait notifacaion");
            TimeUnit.SECONDS.sleep(2);
            System.out.println(mbeanProxy.getName());
            mbeanProxy.sayHi();
            TimeUnit.SECONDS.sleep(10);
            jmxConnector.close();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MalformedObjectNameException e) {
            e.printStackTrace();
        } catch (InstanceNotFoundException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
複製代碼

listener

public class PaxiClientListener implements NotificationListener{
    @Override
    public void handleNotification(Notification notification, Object handback) {
        System.out.println("r notification");
        System.out.println("class:"+notification.getClass().getName());
        System.out.println("Source:"+notification.getSource());
        System.out.println("Type:"+notification.getType());
        System.out.println("Message:"+notification.getMessage());
        if (notification instanceof AttributeChangeNotification){
            AttributeChangeNotification n= (AttributeChangeNotification) notification;
            System.out.println("attr name:"+n.getAttributeName());
            System.out.println("attr type:"+n.getAttributeType());
            System.out.println("attr new Value:"+n.getNewValue());
            System.out.println("attr old Value:"+n.getOldValue());
        }
    }
}
複製代碼

jmx 官方文檔

相關文章
相關標籤/搜索