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.instrumentation;
042:
043: import org.netbeans.lib.profiler.classfile.ClassRepository;
044: import org.netbeans.lib.profiler.classfile.DynamicClassInfo;
045: import org.netbeans.lib.profiler.global.ProfilingSessionStatus;
046: import org.netbeans.lib.profiler.utils.MiscUtils;
047: import java.io.IOException;
048: import java.util.ArrayList;
049: import java.util.Enumeration;
050:
051: /**
052: * A number of miscellaneous, relatively high-level, instrumentation operations.
053: *
054: * @author Misha Dmitriev
055: */
056: public class MiscInstrumentationOps extends ClassManager {
057: //~ Instance fields ----------------------------------------------------------------------------------------------------------
058:
059: private ArrayList instrClasses;
060: private int nInstrClasses;
061: private int nInstrMethods;
062:
063: //~ Constructors -------------------------------------------------------------------------------------------------------------
064:
065: public MiscInstrumentationOps(ProfilingSessionStatus status) {
066: super (status);
067: instrClasses = new ArrayList();
068: }
069:
070: //~ Methods ------------------------------------------------------------------------------------------------------------------
071:
072: public Object[] getOrigCodeForAllInstrumentedMethods() {
073: nInstrClasses = nInstrMethods = 0;
074:
075: for (Enumeration e = ClassRepository
076: .getClassEnumerationWithAllVersions(); e
077: .hasMoreElements();) {
078: Object ci = e.nextElement();
079:
080: if (!(ci instanceof DynamicClassInfo)) {
081: continue; // It's a BaseClassInfo, created just for e.g. array classes, or a PlaceholderClassInfo
082: }
083:
084: DynamicClassInfo clazz = (DynamicClassInfo) ci;
085:
086: if (!clazz.isLoaded()) {
087: continue;
088: }
089:
090: if (!clazz.hasInstrumentedMethods()) {
091: continue;
092: }
093:
094: instrClasses.add(clazz);
095:
096: int nMethods = clazz.getMethodNames().length;
097: int nLocalInstrMethods = 0;
098:
099: for (int i = 0; i < nMethods; i++) {
100: if (clazz.isMethodInstrumented(i)
101: && !clazz.isMethodUnscannable(i)) {
102: nLocalInstrMethods++;
103: }
104: }
105:
106: nInstrClasses++;
107: nInstrMethods += nLocalInstrMethods;
108: }
109:
110: return createInstrumentedMethodPack();
111: }
112:
113: Object[] getOrigCodeForSingleInstrumentedMethod(
114: RootMethods rootMethods) {
115: String className = rootMethods.classNames[ProfilingSessionStatus.CODE_REGION_CLASS_IDX];
116: String methodName = rootMethods.methodNames[ProfilingSessionStatus.CODE_REGION_CLASS_IDX];
117: String methodSignature = rootMethods.methodSignatures[ProfilingSessionStatus.CODE_REGION_CLASS_IDX];
118:
119: ArrayList classes = ClassRepository
120: .getAllClassVersions(className);
121:
122: if (classes == null) {
123: return null; // Can happen if actually nothing was instrumented, since class of intrest hasn't been loaded
124: }
125:
126: methodName = methodName.intern();
127: methodSignature = methodSignature.intern();
128:
129: nInstrClasses = nInstrMethods = 0;
130:
131: for (int i = 0; i < classes.size(); i++) {
132: DynamicClassInfo clazz = (DynamicClassInfo) classes.get(i);
133: int methodIdx = clazz.getMethodIndex(methodName,
134: methodSignature);
135:
136: if (methodIdx != -1) { // Otherwise this method doesn't exist in this class version
137: instrClasses.add(clazz);
138: nInstrClasses++;
139: nInstrMethods++;
140: }
141: }
142:
143: if (nInstrClasses == 0) {
144: MiscUtils
145: .printErrorMessage("got zero classes when attempting to deinstrument a single instrumented method"); // NOI18N
146:
147: return null; // Should not happen, but just in case...
148: }
149:
150: return createInstrumentedMethodPack();
151: }
152:
153: protected Object[] createInstrumentedMethodPack() {
154: if (nInstrMethods == 0) {
155: return null;
156: }
157:
158: return createInstrumentedMethodPack15();
159: }
160:
161: /** Creates the 1.5-style array of instrumented class files. */
162: private Object[] createInstrumentedMethodPack15() {
163: String[] instrMethodClasses = new String[nInstrClasses];
164: int[] instrClassLoaderIds = new int[nInstrClasses];
165: byte[][] replacementClassFileBytes = new byte[nInstrClasses][];
166:
167: for (int j = 0; j < nInstrClasses; j++) {
168: DynamicClassInfo clazz = (DynamicClassInfo) instrClasses
169: .get(j);
170: instrMethodClasses[j] = clazz.getName().replace('/', '.'); // NOI18N
171: instrClassLoaderIds[j] = clazz.getLoaderId();
172:
173: // As an optimization, we now send just nulls for class file bytes to the server, who loads original class file bytes in place
174: //try {
175: // replacementClassFileBytes[j] = clazz.getClassFileBytes();
176: //} catch (IOException ex) {
177: // // Shouldn't happen, so a message just in case
178: // MiscUtils.internalError("MiscInstrumentationOps: can't get original class file bytes for class " + clazz.getName() + "\nIOException message = " + ex.getMessage());
179: //}
180: }
181:
182: return new Object[] { instrMethodClasses, instrClassLoaderIds,
183: replacementClassFileBytes };
184: }
185: }
|