001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.classfile;
042:
043: /**
044: * A table that maps a class loader to its parent class loader.
045: *
046: * @author Misha Dmitirev
047: * @author Ian Formanek
048: */
049: public class ClassLoaderTable {
050: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
051:
052: // TODO [release]: change value to TRUE to remove the print code below entirely by compiler
053: private static final boolean DEBUG = System
054: .getProperty("org.netbeans.lib.profiler.classfile.ClassLoaderTable") != null; // NOI18N
055: private static int[] parentLoaderIds;
056:
057: //~ Methods ------------------------------------------------------------------------------------------------------------------
058:
059: /**
060: * Will provide Id of parent classloader for the specified classloader. The parent of system classloader (id=0)
061: * is the same system classloader (id=0).
062: *
063: * @param loader id of ClassLoader whose parent we are looking for
064: * @return The id of the parent classloader of the specified classloader
065: */
066: public static int getParentLoader(int loader) {
067: if (DEBUG) {
068: System.err
069: .println("ClassLoaderTable.DEBUG: getParent loader: "
070: + loader); // NOI18N
071: }
072:
073: if (loader >= parentLoaderIds.length) {
074: // very stranmge situation: loader not known on tool side, seems like this can happen when using
075: // instrumentation for Method.invoke, where the MethodLoadedCommand comes for class sun.reflect.misc.Trampoline
076: // although the ClassLoadedCommand never is issued for this class
077: return -1;
078: }
079:
080: return parentLoaderIds[loader];
081: }
082:
083: /**
084: * @param thisAndParentLoaderData An array
085: */
086: public static void addChildAndParent(int[] this AndParentLoaderData) {
087: int ofs = this AndParentLoaderData[2];
088:
089: if (ofs == 0) {
090: addChildAndParent(this AndParentLoaderData[0],
091: this AndParentLoaderData[1]);
092: } else {
093: int loaderId = this AndParentLoaderData[0];
094:
095: for (int i = 0; i < ofs; i++) {
096: addChildAndParent(loaderId, loaderId + 1);
097: loaderId++;
098: }
099:
100: addChildAndParent(loaderId, this AndParentLoaderData[1]);
101: }
102: }
103:
104: /**
105: * Will perform initial initialization of the classloader table with data provided from the profiler VM.
106: *
107: * @param inParentLoaderIds table mapping id (idx) -> parent id ([idx])
108: */
109: public static void initTable(int[] inParentLoaderIds) {
110: if (DEBUG) {
111: System.err
112: .println("ClassLoaderTable.DEBUG: init patent loader ids: "
113: + inParentLoaderIds.length); // NOI18N
114:
115: for (int i = 0; i < inParentLoaderIds.length; i++) {
116: System.err
117: .println("ClassLoaderTable.DEBUG: inParentLoaderIds["
118: + i + "]=" + inParentLoaderIds[i]); // NOI18N
119: }
120: }
121:
122: parentLoaderIds = inParentLoaderIds;
123:
124: for (int i = 0; i < parentLoaderIds.length; i++) {
125: // We don't distinguish between bootstrap (-1) and system (0) class loaders, as well as some
126: // sun.reflect.DelegatingClassLoaders or whatever, that also have -1 as their parent.
127: if (parentLoaderIds[i] == -1) {
128: parentLoaderIds[i] = 0;
129: }
130: }
131: }
132:
133: /**
134: * Will add a new pair of classloader, its parent to the table.
135: *
136: * @param childLoader Id of classloader
137: * @param parentLoader Id of its parent classloader
138: */
139: private static void addChildAndParent(int childLoader,
140: int parentLoader) {
141: if (DEBUG) {
142: System.err
143: .println("ClassLoaderTable.DEBUG: add child and parent: child: " // NOI18N
144: + childLoader + ", parent: " // NOI18N
145: + parentLoader);
146: }
147:
148: int maxLoader = (childLoader > parentLoader) ? childLoader
149: : parentLoader;
150:
151: if (parentLoaderIds.length < (maxLoader + 1)) {
152: // new loader, need to enlarge the array
153: int[] oldTable = parentLoaderIds;
154: parentLoaderIds = new int[(childLoader * 2) + 1];
155: System.arraycopy(oldTable, 0, parentLoaderIds, 0,
156: oldTable.length);
157: }
158:
159: if (parentLoader == -1) {
160: parentLoader = 0;
161: }
162:
163: parentLoaderIds[childLoader] = parentLoader;
164: }
165: }
|