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.results.memory;
042:
043: import org.netbeans.lib.profiler.ProfilerClient;
044: import org.netbeans.lib.profiler.client.ClientUtils;
045: import java.io.DataInputStream;
046: import java.io.DataOutputStream;
047: import java.io.IOException;
048:
049: /**
050: * This class maps jmethodIds to (clazz, methodIdx) pairs
051: *
052: * @author Misha Dmitriev
053: */
054: public class JMethodIdTable {
055: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
056:
057: static class JMethodIdTableEntry {
058: //~ Instance fields ------------------------------------------------------------------------------------------------------
059:
060: String className;
061: String methodName;
062: String methodSig;
063: int methodId;
064:
065: //~ Constructors ---------------------------------------------------------------------------------------------------------
066:
067: JMethodIdTableEntry(int methodId) {
068: this .methodId = methodId;
069: }
070: }
071:
072: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
073:
074: private static JMethodIdTable defaultTable;
075:
076: //~ Instance fields ----------------------------------------------------------------------------------------------------------
077:
078: private JMethodIdTableEntry[] entries;
079: private boolean staticTable = false;
080: private int incompleteEntries;
081: private int nElements;
082: private int size;
083: private int threshold;
084:
085: //~ Constructors -------------------------------------------------------------------------------------------------------------
086:
087: JMethodIdTable() {
088: size = 97;
089: threshold = (size * 3) / 4;
090: nElements = 0;
091: entries = new JMethodIdTableEntry[size];
092: }
093:
094: JMethodIdTable(int[] methodIds, String[][] methodNamesAndSigs) {
095: staticTable = true;
096: size = methodIds.length * 2; // TODO: check this
097: threshold = (size * 3) / 4;
098: nElements = 0;
099: entries = new JMethodIdTableEntry[size];
100:
101: for (int i = 0; i < methodIds.length; i++) {
102: addEntry(methodIds[i], methodNamesAndSigs[0][i],
103: methodNamesAndSigs[1][i], methodNamesAndSigs[2][i]);
104: }
105: }
106:
107: //~ Methods ------------------------------------------------------------------------------------------------------------------
108:
109: public static JMethodIdTable getDefault() {
110: if (defaultTable == null) {
111: defaultTable = new JMethodIdTable();
112: }
113:
114: return defaultTable;
115: }
116:
117: public static void reset() {
118: defaultTable = null;
119: }
120:
121: public String debug() {
122: if (entries == null) {
123: return "Entries = null, size = " + size + ", nElements = "
124: + nElements
125: + ", threshold = " // NOI18N
126: + threshold + ", incompleteEntries = "
127: + incompleteEntries; // NOI18N
128: } else {
129: return "Entries.length = " + entries.length + ", size = "
130: + size + ", nElements = "
131: + nElements // NOI18N
132: + ", threshold = " + threshold
133: + ", incompleteEntries = " + incompleteEntries; // NOI18N
134: }
135: }
136:
137: public void readFromStream(DataInputStream in) throws IOException {
138: size = in.readInt();
139: nElements = in.readInt();
140: threshold = in.readInt();
141:
142: entries = new JMethodIdTableEntry[size];
143:
144: int count = in.readInt();
145:
146: for (int i = 0; i < count; i++) {
147: int methodId = in.readInt();
148: String className = in.readUTF();
149: String methodName = in.readUTF();
150: String methodSig = in.readUTF();
151:
152: addEntry(methodId, className, methodName, methodSig);
153: }
154: }
155:
156: public void writeToStream(DataOutputStream out) throws IOException {
157: out.writeInt(size);
158: out.writeInt(nElements);
159: out.writeInt(threshold);
160:
161: int count = 0;
162:
163: for (int i = 0; i < entries.length; i++) {
164: if (entries[i] != null) {
165: count++;
166: }
167: }
168:
169: out.writeInt(count);
170:
171: for (int i = 0; i < entries.length; i++) {
172: if (entries[i] != null) {
173: out.writeInt(entries[i].methodId);
174: out.writeUTF(entries[i].className);
175: out.writeUTF(entries[i].methodName);
176: out.writeUTF(entries[i].methodSig);
177: }
178: }
179: }
180:
181: JMethodIdTableEntry getEntry(int methodId) {
182: int pos = hash(methodId) % size;
183:
184: while ((entries[pos] != null)
185: && (entries[pos].methodId != methodId)) {
186: pos = (pos + 1) % size;
187: }
188:
189: return entries[pos];
190: }
191:
192: synchronized void getNamesForMethodIds(ProfilerClient profilerClient)
193: throws ClientUtils.TargetAppOrVMTerminated {
194: if (staticTable) {
195: throw new IllegalStateException(
196: "Attempt to update snapshot JMethodIdTable"); // NOI18N
197: }
198:
199: if (incompleteEntries == 0) {
200: return;
201: }
202:
203: int[] missingNameMethodIds = new int[incompleteEntries];
204: int idx = 0;
205:
206: for (int i = 0; i < entries.length; i++) {
207: if (entries[i] == null) {
208: continue;
209: }
210:
211: if (entries[i].className == null) {
212: missingNameMethodIds[idx++] = entries[i].methodId;
213: }
214: }
215:
216: String[][] methodClassNameAndSig = profilerClient
217: .getMethodNamesForJMethodIds(missingNameMethodIds);
218:
219: for (int i = 0; i < missingNameMethodIds.length; i++) {
220: completeEntry(missingNameMethodIds[i],
221: methodClassNameAndSig[0][i],
222: methodClassNameAndSig[1][i],
223: methodClassNameAndSig[2][i]);
224: }
225:
226: incompleteEntries = 0;
227: }
228:
229: void addEntry(int methodId, String className, String methodName,
230: String methodSig) {
231: checkMethodId(methodId);
232: completeEntry(methodId, className, methodName, methodSig);
233: }
234:
235: synchronized void checkMethodId(int methodId) {
236: int pos = hash(methodId) % size;
237:
238: while (entries[pos] != null) {
239: if (entries[pos].methodId == methodId) {
240: return;
241: }
242:
243: pos = (pos + 1) % size;
244: }
245:
246: if (nElements < threshold) {
247: entries[pos] = new JMethodIdTableEntry(methodId);
248: nElements++;
249: incompleteEntries++;
250:
251: return;
252: } else {
253: growTable();
254: checkMethodId(methodId);
255: }
256: }
257:
258: private void completeEntry(int methodId, String className,
259: String methodName, String methodSig) {
260: int pos = hash(methodId) % size;
261:
262: while (entries[pos].methodId != methodId) {
263: pos = (pos + 1) % size;
264: }
265:
266: entries[pos].className = className;
267: entries[pos].methodName = methodName;
268: entries[pos].methodSig = methodSig;
269: }
270:
271: private void growTable() {
272: JMethodIdTableEntry[] oldEntries = entries;
273: size = (size * 2) + 1;
274: threshold = (size * 3) / 4;
275: entries = new JMethodIdTableEntry[size];
276:
277: for (int i = 0; i < oldEntries.length; i++) {
278: if (oldEntries[i] != null) {
279: int pos = hash(oldEntries[i].methodId) % size;
280:
281: while (entries[pos] != null) {
282: pos = (pos + 1) % size;
283: }
284:
285: entries[pos] = oldEntries[i];
286: }
287: }
288: }
289:
290: private int hash(int x) {
291: return ((x >> 2) * 123457) & 0xFFFFFFF;
292: }
293: }
|