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+
26+package com.sun.jmx.mbeanserver;
27+
28+
29+import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
30+import java.util.ArrayList;
31+import java.util.Arrays;
32+import java.util.Hashtable;
33+import java.util.List;
34+import java.util.Map;
35+import java.util.logging.Level;
36+
37+import javax.management.ObjectName;
38+import 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+ */
47+final 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+}