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/tracing/ProviderSkeleton.java
38829 views
1
/*
2
* Copyright (c) 2008, 2013, 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.tracing;
27
28
import java.lang.reflect.InvocationHandler;
29
import java.lang.reflect.Method;
30
import java.lang.reflect.Proxy;
31
import java.lang.reflect.InvocationTargetException;
32
import java.lang.reflect.AnnotatedElement;
33
import java.lang.annotation.Annotation;
34
import java.util.HashMap;
35
import java.security.AccessController;
36
import java.security.PrivilegedAction;
37
38
import com.sun.tracing.Provider;
39
import com.sun.tracing.Probe;
40
import com.sun.tracing.ProviderName;
41
42
/**
43
* Provides a common code for implementation of {@code Provider} classes.
44
*
45
* Each tracing subsystem needs to provide three classes, a factory
46
* (derived from {@code ProviderFactory}, a provider (a subclass of
47
* {@code Provider}, and a probe type (subclass of {@code ProbeSkeleton}).
48
*
49
* The factory object takes a user-defined interface and provides an
50
* implementation of it whose method calls will trigger probes in the
51
* tracing framework.
52
*
53
* The framework's provider class, and its instances, are not seen by the
54
* user at all -- they usually sit in the background and receive and dispatch
55
* the calls to the user's provider interface. The {@code ProviderSkeleton}
56
* class provides almost all of the implementation needed by a framework
57
* provider. Framework providers must only provide a constructor and
58
* disposal method, and implement the {@code createProbe} method to create
59
* an appropriate {@code ProbeSkeleton} subclass.
60
*
61
* The framework's probe class provides the implementation of the two
62
* probe methods, {@code isEnabled()} and {@code uncheckedTrigger()}. Both are
63
* framework-dependent implementations.
64
*
65
* @since 1.7
66
*/
67
68
public abstract class ProviderSkeleton implements InvocationHandler, Provider {
69
70
protected boolean active; // set to false after dispose() is called
71
protected Class<? extends Provider> providerType; // user's interface
72
protected HashMap<Method, ProbeSkeleton> probes; // methods to probes
73
74
75
/**
76
* Creates a framework-specific probe subtype.
77
*
78
* This method is implemented by the framework's provider and returns
79
* framework-specific probes for a method.
80
*
81
* @param method A method in the user's interface
82
* @return a subclass of ProbeSkeleton for the particular framework.
83
*/
84
protected abstract ProbeSkeleton createProbe(Method method);
85
86
/**
87
* Initializes the provider.
88
*
89
* @param type the user's interface
90
*/
91
protected ProviderSkeleton(Class<? extends Provider> type) {
92
this.active = false; // in case of some error during initialization
93
this.providerType = type;
94
this.probes = new HashMap<Method,ProbeSkeleton>();
95
}
96
97
/**
98
* Post-constructor initialization routine.
99
*
100
* Subclass instances must be initialized before they can create probes.
101
* It is up to the factory implementations to call this after construction.
102
*/
103
public void init() {
104
Method[] methods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
105
public Method[] run() {
106
return providerType.getDeclaredMethods();
107
}
108
});
109
110
for (Method m : methods) {
111
if ( m.getReturnType() != Void.TYPE ) {
112
throw new IllegalArgumentException(
113
"Return value of method is not void");
114
} else {
115
probes.put(m, createProbe(m));
116
}
117
}
118
this.active = true;
119
}
120
121
/**
122
* Magic routine which creates an implementation of the user's interface.
123
*
124
* This method creates the instance of the user's interface which is
125
* passed back to the user. Every call upon that interface will be
126
* redirected to the {@code invoke()} method of this class (until
127
* overridden by the VM).
128
*
129
* @return an implementation of the user's interface
130
*/
131
@SuppressWarnings("unchecked")
132
public <T extends Provider> T newProxyInstance() {
133
final InvocationHandler ih = this;
134
return AccessController.doPrivileged(new PrivilegedAction<T>() {
135
public T run() {
136
return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
137
new Class<?>[] { providerType }, ih);
138
}});
139
}
140
141
/**
142
* Triggers a framework probe when a user interface method is called.
143
*
144
* This method dispatches a user interface method call to the appropriate
145
* probe associated with this framework.
146
*
147
* If the invoked method is not a user-defined member of the interface,
148
* then it is a member of {@code Provider} or {@code Object} and we
149
* invoke the method directly.
150
*
151
* @param proxy the instance whose method was invoked
152
* @param method the method that was called
153
* @param args the arguments passed in the call.
154
* @return always null, if the method is a user-defined probe
155
*/
156
public Object invoke(Object proxy, Method method, Object[] args) {
157
Class declaringClass = method.getDeclaringClass();
158
// not a provider subtype's own method
159
if (declaringClass != providerType) {
160
try {
161
// delegate only to methods declared by
162
// com.sun.tracing.Provider or java.lang.Object
163
if (declaringClass == Provider.class ||
164
declaringClass == Object.class) {
165
return method.invoke(this, args);
166
} else {
167
// assert false : "this should never happen"
168
// reaching here would indicate a breach
169
// in security in the higher layers
170
throw new SecurityException();
171
}
172
} catch (IllegalAccessException e) {
173
assert false;
174
} catch (InvocationTargetException e) {
175
assert false;
176
}
177
} else {
178
triggerProbe(method, args);
179
}
180
return null;
181
}
182
183
/**
184
* Direct accessor for {@code Probe} objects.
185
*
186
* @param m the method corresponding to a probe
187
* @return the method associated probe object, or null
188
*/
189
public Probe getProbe(Method m) {
190
return active ? probes.get(m) : null;
191
}
192
193
/**
194
* Default provider disposal method.
195
*
196
* This is overridden in subclasses as needed.
197
*/
198
public void dispose() {
199
active = false;
200
probes.clear();
201
}
202
203
/**
204
* Gets the user-specified provider name for the user's interface.
205
*
206
* If the user's interface has a {@ProviderName} annotation, that value
207
* is used. Otherwise we use the simple name of the user interface's class.
208
* @return the provider name
209
*/
210
protected String getProviderName() {
211
return getAnnotationString(
212
providerType, ProviderName.class, providerType.getSimpleName());
213
}
214
215
/**
216
* Utility method for getting a string value from an annotation.
217
*
218
* Used for getting a string value from an annotation with a 'value' method.
219
*
220
* @param element the element that was annotated, either a class or method
221
* @param annotation the class of the annotation we're interested in
222
* @param defaultValue the value to return if the annotation doesn't
223
* exist, doesn't have a "value", or the value is empty.
224
*/
225
protected static String getAnnotationString(
226
AnnotatedElement element, Class<? extends Annotation> annotation,
227
String defaultValue) {
228
String ret = (String)getAnnotationValue(
229
element, annotation, "value", defaultValue);
230
return ret.isEmpty() ? defaultValue : ret;
231
}
232
233
/**
234
* Utility method for calling an arbitrary method in an annotation.
235
*
236
* @param element the element that was annotated, either a class or method
237
* @param annotation the class of the annotation we're interested in
238
* @param methodName the name of the method in the annotation we wish
239
* to call.
240
* @param defaultValue the value to return if the annotation doesn't
241
* exist, or we couldn't invoke the method for some reason.
242
* @return the result of calling the annotation method, or the default.
243
*/
244
protected static Object getAnnotationValue(
245
AnnotatedElement element, Class<? extends Annotation> annotation,
246
String methodName, Object defaultValue) {
247
Object ret = defaultValue;
248
try {
249
Method m = annotation.getMethod(methodName);
250
Annotation a = element.getAnnotation(annotation);
251
ret = m.invoke(a);
252
} catch (NoSuchMethodException e) {
253
assert false;
254
} catch (IllegalAccessException e) {
255
assert false;
256
} catch (InvocationTargetException e) {
257
assert false;
258
} catch (NullPointerException e) {
259
assert false;
260
}
261
return ret;
262
}
263
264
protected void triggerProbe(Method method, Object[] args) {
265
if (active) {
266
ProbeSkeleton p = probes.get(method);
267
if (p != null) {
268
// Skips argument check -- already done by javac
269
p.uncheckedTrigger(args);
270
}
271
}
272
}
273
}
274
275