History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java+304−0
@@ -0,0 +1,304 @@
1/*
2 * Copyright (c) 2002, 2008, 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.jmx.mbeanserver;
27
28
29import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
30import java.util.ArrayList;
31import java.util.Arrays;
32import java.util.Hashtable;
33import java.util.List;
34import java.util.Map;
35import java.util.logging.Level;
36
37import javax.management.ObjectName;
38import javax.management.loading.PrivateClassLoader;
39
40/**
41 * This class keeps the list of Class Loaders registered in the MBean Server.
42 * It provides the necessary methods to load classes using the
43 * registered Class Loaders.
44 *
45 * @since 1.5
46 */
47final class ClassLoaderRepositorySupport
48 implements ModifiableClassLoaderRepository {
49
50 /* We associate an optional ObjectName with each entry so that
51 we can remove the correct entry when unregistering an MBean
52 that is a ClassLoader. The same object could be registered
53 under two different names (even though this is not recommended)
54 so if we did not do this we could disturb the defined
55 semantics for the order of ClassLoaders in the repository. */
56 private static class LoaderEntry {
57 ObjectName name; // can be null
58 ClassLoader loader;
59
60 LoaderEntry(ObjectName name, ClassLoader loader) {
61 this.name = name;
62 this.loader = loader;
63 }
64 }
65
66 private static final LoaderEntry[] EMPTY_LOADER_ARRAY = new LoaderEntry[0];
67
68 /**
69 * List of class loaders
70 * Only read-only actions should be performed on this object.
71 *
72 * We do O(n) operations on this array, e.g. when removing
73 * a ClassLoader. The assumption is that the number of elements
74 * is small, probably less than ten, and that the vast majority
75 * of operations are searches (loadClass) which are by definition
76 * linear.
77 */
78 private LoaderEntry[] loaders = EMPTY_LOADER_ARRAY;
79
80 /**
81 * Same behavior as add(Object o) in {@link java.util.List}.
82 * Replace the loader list with a new one in which the new
83 * loader has been added.
84 **/
85 private synchronized boolean add(ObjectName name, ClassLoader cl) {
86 List<LoaderEntry> l =
87 new ArrayList<LoaderEntry>(Arrays.asList(loaders));
88 l.add(new LoaderEntry(name, cl));
89 loaders = l.toArray(EMPTY_LOADER_ARRAY);
90 return true;
91 }
92
93 /**
94 * Same behavior as remove(Object o) in {@link java.util.List}.
95 * Replace the loader list with a new one in which the old loader
96 * has been removed.
97 *
98 * The ObjectName may be null, in which case the entry to
99 * be removed must also have a null ObjectName and the ClassLoader
100 * values must match. If the ObjectName is not null, then
101 * the first entry with a matching ObjectName is removed,
102 * regardless of whether ClassLoader values match. (In fact,
103 * the ClassLoader parameter will usually be null in this case.)
104 **/
105 private synchronized boolean remove(ObjectName name, ClassLoader cl) {
106 final int size = loaders.length;
107 for (int i = 0; i < size; i++) {
108 LoaderEntry entry = loaders[i];
109 boolean match =
110 (name == null) ?
111 cl == entry.loader :
112 name.equals(entry.name);
113 if (match) {
114 LoaderEntry[] newloaders = new LoaderEntry[size - 1];
115 System.arraycopy(loaders, 0, newloaders, 0, i);
116 System.arraycopy(loaders, i + 1, newloaders, i,
117 size - 1 - i);
118 loaders = newloaders;
119 return true;
120 }
121 }
122 return false;
123 }
124
125
126 /**
127 * List of valid search
128 */
129 private final Map<String,List<ClassLoader>> search =
130 new Hashtable<String,List<ClassLoader>>(10);
131
132 /**
133 * List of named class loaders.
134 */
135 private final Map<ObjectName,ClassLoader> loadersWithNames =
136 new Hashtable<ObjectName,ClassLoader>(10);
137
138 // from javax.management.loading.DefaultLoaderRepository
139 public final Class<?> loadClass(String className)
140 throws ClassNotFoundException {
141 return loadClass(loaders, className, null, null);
142 }
143
144
145 // from javax.management.loading.DefaultLoaderRepository
146 public final Class<?> loadClassWithout(ClassLoader without, String className)
147 throws ClassNotFoundException {
148 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
149 MBEANSERVER_LOGGER.logp(Level.FINER,
150 ClassLoaderRepositorySupport.class.getName(),
151 "loadClassWithout", className + " without " + without);
152 }
153
154 // without is null => just behave as loadClass
155 //
156 if (without == null)
157 return loadClass(loaders, className, null, null);
158
159 // We must try to load the class without the given loader.
160 //
161 startValidSearch(without, className);
162 try {
163 return loadClass(loaders, className, without, null);
164 } finally {
165 stopValidSearch(without, className);
166 }
167 }
168
169
170 public final Class<?> loadClassBefore(ClassLoader stop, String className)
171 throws ClassNotFoundException {
172 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
173 MBEANSERVER_LOGGER.logp(Level.FINER,
174 ClassLoaderRepositorySupport.class.getName(),
175 "loadClassBefore", className + " before " + stop);
176 }
177
178 if (stop == null)
179 return loadClass(loaders, className, null, null);
180
181 startValidSearch(stop, className);
182 try {
183 return loadClass(loaders, className, null, stop);
184 } finally {
185 stopValidSearch(stop, className);
186 }
187 }
188
189
190 private Class<?> loadClass(final LoaderEntry list[],
191 final String className,
192 final ClassLoader without,
193 final ClassLoader stop)
194 throws ClassNotFoundException {
195 final int size = list.length;
196 for(int i=0; i<size; i++) {
197 try {
198 final ClassLoader cl = list[i].loader;
199 if (cl == null) // bootstrap class loader
200 return Class.forName(className, false, null);
201 if (cl == without)
202 continue;
203 if (cl == stop)
204 break;
205 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
206 MBEANSERVER_LOGGER.logp(Level.FINER,
207 ClassLoaderRepositorySupport.class.getName(),
208 "loadClass", "Trying loader = " + cl);
209 }
210 /* We used to have a special case for "instanceof
211 MLet" here, where we invoked the method
212 loadClass(className, null) to prevent infinite
213 recursion. But the rule whereby the MLet only
214 consults loaders that precede it in the CLR (via
215 loadClassBefore) means that the recursion can't
216 happen, and the test here caused some legitimate
217 classloading to fail. For example, if you have
218 dependencies C->D->E with loaders {E D C} in the
219 CLR in that order, you would expect to be able to
220 load C. The problem is that while resolving D, CLR
221 delegation is disabled, so it can't find E. */
222 return Class.forName(className, false, cl);
223 } catch (ClassNotFoundException e) {
224 // OK: continue with next class
225 }
226 }
227
228 throw new ClassNotFoundException(className);
229 }
230
231 private synchronized void startValidSearch(ClassLoader aloader,
232 String className)
233 throws ClassNotFoundException {
234 // Check if we have such a current search
235 //
236 List<ClassLoader> excluded = search.get(className);
237 if ((excluded!= null) && (excluded.contains(aloader))) {
238 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
239 MBEANSERVER_LOGGER.logp(Level.FINER,
240 ClassLoaderRepositorySupport.class.getName(),
241 "startValidSearch", "Already requested loader = " +
242 aloader + " class = " + className);
243 }
244 throw new ClassNotFoundException(className);
245 }
246
247 // Add an entry
248 //
249 if (excluded == null) {
250 excluded = new ArrayList<ClassLoader>(1);
251 search.put(className, excluded);
252 }
253 excluded.add(aloader);
254 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
255 MBEANSERVER_LOGGER.logp(Level.FINER,
256 ClassLoaderRepositorySupport.class.getName(),
257 "startValidSearch",
258 "loader = " + aloader + " class = " + className);
259 }
260 }
261
262 private synchronized void stopValidSearch(ClassLoader aloader,
263 String className) {
264
265 // Retrieve the search.
266 //
267 List<ClassLoader> excluded = search.get(className);
268 if (excluded != null) {
269 excluded.remove(aloader);
270 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
271 MBEANSERVER_LOGGER.logp(Level.FINER,
272 ClassLoaderRepositorySupport.class.getName(),
273 "stopValidSearch",
274 "loader = " + aloader + " class = " + className);
275 }
276 }
277 }
278
279 public final void addClassLoader(ClassLoader loader) {
280 add(null, loader);
281 }
282
283 public final void removeClassLoader(ClassLoader loader) {
284 remove(null, loader);
285 }
286
287 public final synchronized void addClassLoader(ObjectName name,
288 ClassLoader loader) {
289 loadersWithNames.put(name, loader);
290 if (!(loader instanceof PrivateClassLoader))
291 add(name, loader);
292 }
293
294 public final synchronized void removeClassLoader(ObjectName name) {
295 ClassLoader loader = loadersWithNames.remove(name);
296 if (!(loader instanceof PrivateClassLoader))
297 remove(name, loader);
298 }
299
300 public final ClassLoader getClassLoader(ObjectName name) {
301 return loadersWithNames.get(name);
302 }
303
304}