1/*
2 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.management.internal;
27
28import com.sun.management.GarbageCollectionNotificationInfo;
29import com.sun.management.GarbageCollectorMXBean;
30import com.sun.management.GcInfo;
31import java.lang.management.ManagementFactory;
32import java.lang.management.MemoryPoolMXBean;
33import java.util.List;
34import javax.management.ListenerNotFoundException;
35import javax.management.MBeanNotificationInfo;
36import javax.management.Notification;
37import javax.management.NotificationFilter;
38import javax.management.NotificationListener;
39import javax.management.openmbean.CompositeData;
40import sun.management.GarbageCollectorImpl;
41
42/**
43 * Implementation class for the garbage collector.
44 * Standard and committed hotspot-specific metrics if any.
45 *
46 * ManagementFactory.getGarbageCollectorMXBeans() returns a list
47 * of instances of this class.
48 */
49public class GarbageCollectorExtImpl extends GarbageCollectorImpl
50    implements GarbageCollectorMXBean {
51
52    public GarbageCollectorExtImpl(String name) {
53        super(name);
54    }
55
56    // The memory pools are static and won't be changed.
57    // TODO: If the hotspot implementation begins to have pools
58    // dynamically created and removed, this needs to be modified.
59    private String[] poolNames = null;
60    private synchronized String[] getAllPoolNames() {
61        if (poolNames == null) {
62            List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
63            poolNames = new String[pools.size()];
64            int i = 0;
65            for (MemoryPoolMXBean m : pools) {
66                poolNames[i++] = m.getName();
67            }
68        }
69        return poolNames;
70    }
71
72    public GcInfo getLastGcInfo() {
73        GcInfo info = getGcInfoBuilder().getLastGcInfo();
74        return info;
75    }
76
77    private final static String notifName =
78        "javax.management.Notification";
79
80    private final static String[] gcNotifTypes = {
81        GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION
82    };
83
84    public MBeanNotificationInfo[] getNotificationInfo() {
85        return new MBeanNotificationInfo[]{
86            new MBeanNotificationInfo(gcNotifTypes,
87            notifName,
88            "GC Notification")
89        };
90    }
91
92    private static long seqNumber = 0;
93    private static long getNextSeqNumber() {
94        return ++seqNumber;
95    }
96
97    protected void createGCNotification(long timestamp,
98                              String gcName,
99                              String gcAction,
100                              String gcCause,
101                              GcInfo gcInfo)  {
102        if (!hasListeners()) {
103            return;
104        }
105        Notification notif = new Notification(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
106                                              getObjectName(),
107                                              getNextSeqNumber(),
108                                              timestamp,
109                                              gcName);
110        GarbageCollectionNotificationInfo info =
111            new GarbageCollectionNotificationInfo(gcName,
112                                                  gcAction,
113                                                  gcCause,
114                                                  gcInfo);
115
116        CompositeData cd =
117            GarbageCollectionNotifInfoCompositeData.toCompositeData(info);
118        notif.setUserData(cd);
119        sendNotification(notif);
120    }
121
122    public synchronized void addNotificationListener(NotificationListener listener,
123                                                     NotificationFilter filter,
124                                                     Object handback)
125    {
126        boolean before = hasListeners();
127        super.addNotificationListener(listener, filter, handback);
128        boolean after = hasListeners();
129        if (!before && after) {
130            setNotificationEnabled(this, true);
131        }
132    }
133
134    public synchronized void removeNotificationListener(NotificationListener listener)
135        throws ListenerNotFoundException {
136        boolean before = hasListeners();
137        super.removeNotificationListener(listener);
138        boolean after = hasListeners();
139
140        if (before && !after) {
141            setNotificationEnabled(this,false);
142        }
143    }
144
145    public synchronized void removeNotificationListener(NotificationListener listener,
146                                                        NotificationFilter filter,
147                                                        Object handback)
148            throws ListenerNotFoundException
149    {
150        boolean before = hasListeners();
151        super.removeNotificationListener(listener,filter,handback);
152        boolean after = hasListeners();
153        if (before && !after) {
154            setNotificationEnabled(this,false);
155        }
156    }
157
158    private GcInfoBuilder gcInfoBuilder;
159    // Invoked also by the VM
160    private synchronized GcInfoBuilder getGcInfoBuilder() {
161        if(gcInfoBuilder == null) {
162            gcInfoBuilder = new GcInfoBuilder(this, getAllPoolNames());
163        }
164        return gcInfoBuilder;
165    }
166
167    private native void setNotificationEnabled(GarbageCollectorMXBean gc,
168                                                 boolean enabled);
169
170    // Invoked by the VM
171    private static java.lang.management.GarbageCollectorMXBean
172        createGarbageCollector(String name, String type) {
173
174        return new GarbageCollectorExtImpl(name);
175    }
176}
177