Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/management/NotificationEmitterSupport.java
38827 views
1
/*
2
* Copyright (c) 2003, 2012, 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
26
package sun.management;
27
28
import javax.management.ListenerNotFoundException;
29
import javax.management.MBeanNotificationInfo;
30
import javax.management.Notification;
31
import javax.management.NotificationEmitter;
32
import javax.management.NotificationFilter;
33
import javax.management.NotificationListener;
34
35
import java.util.List;
36
import java.util.ArrayList;
37
import java.util.ListIterator;
38
import java.util.Collections;
39
40
/**
41
* Abstract helper class for notification emitter support.
42
*/
43
abstract class NotificationEmitterSupport implements NotificationEmitter {
44
45
protected NotificationEmitterSupport() {
46
}
47
48
private Object listenerLock = new Object();
49
50
// Implementation of NotificationEmitter interface
51
// Cloned from JMX NotificationBroadcasterSupport class.
52
public void addNotificationListener(NotificationListener listener,
53
NotificationFilter filter,
54
Object handback) {
55
56
if (listener == null) {
57
throw new IllegalArgumentException ("Listener can't be null") ;
58
}
59
60
/* Adding a new listener takes O(n) time where n is the number
61
of existing listeners. If you have a very large number of
62
listeners performance could degrade. That's a fairly
63
surprising configuration, and it is hard to avoid this
64
behaviour while still retaining the property that the
65
listenerList is not synchronized while notifications are
66
being sent through it. If this becomes a problem, a
67
possible solution would be a multiple-readers single-writer
68
setup, so any number of sendNotification() calls could run
69
concurrently but they would exclude an
70
add/removeNotificationListener. A simpler but less
71
efficient solution would be to clone the listener list
72
every time a notification is sent. */
73
synchronized (listenerLock) {
74
List<ListenerInfo> newList = new ArrayList<>(listenerList.size() + 1);
75
newList.addAll(listenerList);
76
newList.add(new ListenerInfo(listener, filter, handback));
77
listenerList = newList;
78
}
79
}
80
81
public void removeNotificationListener(NotificationListener listener)
82
throws ListenerNotFoundException {
83
84
synchronized (listenerLock) {
85
List<ListenerInfo> newList = new ArrayList<>(listenerList);
86
/* We scan the list of listeners in reverse order because
87
in forward order we would have to repeat the loop with
88
the same index after a remove. */
89
for (int i=newList.size()-1; i>=0; i--) {
90
ListenerInfo li = newList.get(i);
91
92
if (li.listener == listener)
93
newList.remove(i);
94
}
95
if (newList.size() == listenerList.size())
96
throw new ListenerNotFoundException("Listener not registered");
97
listenerList = newList;
98
}
99
}
100
101
public void removeNotificationListener(NotificationListener listener,
102
NotificationFilter filter,
103
Object handback)
104
throws ListenerNotFoundException {
105
106
boolean found = false;
107
108
synchronized (listenerLock) {
109
List<ListenerInfo> newList = new ArrayList<>(listenerList);
110
final int size = newList.size();
111
for (int i = 0; i < size; i++) {
112
ListenerInfo li = newList.get(i);
113
114
if (li.listener == listener) {
115
found = true;
116
if (li.filter == filter
117
&& li.handback == handback) {
118
newList.remove(i);
119
listenerList = newList;
120
return;
121
}
122
}
123
}
124
}
125
126
if (found) {
127
/* We found this listener, but not with the given filter
128
* and handback. A more informative exception message may
129
* make debugging easier. */
130
throw new ListenerNotFoundException("Listener not registered " +
131
"with this filter and " +
132
"handback");
133
} else {
134
throw new ListenerNotFoundException("Listener not registered");
135
}
136
}
137
138
void sendNotification(Notification notification) {
139
140
if (notification == null) {
141
return;
142
}
143
144
List<ListenerInfo> currentList;
145
synchronized (listenerLock) {
146
currentList = listenerList;
147
}
148
149
final int size = currentList.size();
150
for (int i = 0; i < size; i++) {
151
ListenerInfo li = currentList.get(i);
152
153
if (li.filter == null
154
|| li.filter.isNotificationEnabled(notification)) {
155
try {
156
li.listener.handleNotification(notification, li.handback);
157
} catch (Exception e) {
158
e.printStackTrace();
159
throw new AssertionError("Error in invoking listener");
160
}
161
}
162
}
163
}
164
165
boolean hasListeners() {
166
synchronized (listenerLock) {
167
return !listenerList.isEmpty();
168
}
169
}
170
171
private class ListenerInfo {
172
public NotificationListener listener;
173
NotificationFilter filter;
174
Object handback;
175
176
public ListenerInfo(NotificationListener listener,
177
NotificationFilter filter,
178
Object handback) {
179
this.listener = listener;
180
this.filter = filter;
181
this.handback = handback;
182
}
183
}
184
185
/**
186
* Current list of listeners, a List of ListenerInfo. The object
187
* referenced by this field is never modified. Instead, the field
188
* is set to a new object when a listener is added or removed,
189
* within a synchronized(this). In this way, there is no need to
190
* synchronize when traversing the list to send a notification to
191
* the listeners in it. That avoids potential deadlocks if the
192
* listeners end up depending on other threads that are themselves
193
* accessing this NotificationBroadcasterSupport.
194
*/
195
private List<ListenerInfo> listenerList = Collections.emptyList();
196
197
abstract public MBeanNotificationInfo[] getNotificationInfo();
198
}
199
200