fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER START
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * The contents of this file are subject to the terms of the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Common Development and Distribution License (the "License").
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * You may not use this file except in compliance with the License.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * See the License for the specific language governing permissions
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * and limitations under the License.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * When distributing Covered Code, include this CDDL HEADER in each
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If applicable, add the following below this CDDL HEADER, with the
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * fields enclosed by brackets "[]" replaced with your own identifying
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * information: Portions Copyright [yyyy] [name of copyright owner]
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER END
e77b06d21580f630e0a7c437495ab283d3672828tomee * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Use is subject to license terms.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * ident "%Z%%M% %I% %E% SMI"
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * A value generated by the DTrace {@code stack()} action.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Immutable. Supports persistence using {@link java.beans.XMLEncoder}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @author Tom Erickson
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeepublic final class KernelStackRecord implements StackValueRecord,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static final long serialVersionUID = 8616454544771346573L;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static final StackFrame[] EMPTY_FRAMES = new StackFrame[] {};
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee BeanInfo info = Introspector.getBeanInfo(KernelStackRecord.class);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Need to prevent DefaultPersistenceDelegate from using
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * overridden equals() method, resulting in a
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * StackOverFlowError. Revert to PersistenceDelegate
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * implementation. See
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * 477019&tstart=135
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee protected boolean
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee d.setValue("persistenceDelegate", persistenceDelegate);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Splits formatted call stack generated by DTrace stack() and
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * ustack() actions into tokens delimited by whitespace. Matches
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * any number of whitespace characters on either side of a newline.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Can't assume that a line has no whitespace characters. A java
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * stack might have the line "StubRoutines (1)", which must not get
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * split into two tokens.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static final Pattern STACK_TOKENIZER = Pattern.compile("\\s*\n\\s*");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Called by JNI layer to convert a stack formatted by the native
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * DTrace library into an unformatted array of stack frames.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @param s string representation of stack data generated by the D
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code stack()}, {@code ustack()}, or {@code jstack()} action
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @return array of human-readable stack frames
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // First trim the leading whitespace to avoid an initial empty
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // element in the returned array.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (int i = 0; i < n; ++i) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /** @serial */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /** @serial */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Called by native code and by UserStackRecord (in its constructor
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * called by native code).
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @throws NullPointerException if rawBytes is {@code null}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // No need for defensive copy; native code will not modify input
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // raw bytes.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee throw new NullPointerException("raw stack data is null");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Creates a {@code KernelStackRecord} with the given stack frames
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * and raw stack data. Supports XML persistence.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @param frames array of human-readable stack frames, copied so
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * that later modifying the given frames array will not affect this
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code KernelStackRecord}; may be {@code null} or empty to
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * indicate that the raw stack data was not converted to
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * human-readable stack frames (see {@link
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * StackValueRecord#getStackFrames()})
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @param rawBytes array of raw bytes used to represent this stack
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * value in the native DTrace library, needed to distinguish stacks
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * that have the same display value but are considered distinct by
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * DTrace; copied so that later modifying the given array will not
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * affect this {@code KernelStackRecord}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @throws NullPointerException if the given array of raw bytes is
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code null} or if any element of the {@code frames} array is
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code null}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee KernelStackRecord(StackFrame[] frames, byte[] rawBytes)
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee private final void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee throw new NullPointerException("raw stack data is null");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // stackFrames may be null; if non-null, cannot contain null
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // elements
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (f == null) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee throw new NullPointerException("stack frame is null");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Called by native code and by UserStackRecord in its
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * setStackFrames() method.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // No need for defensive copy; native code will not modify input
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Gets the native DTrace representation of this record's stack as
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * an array of raw bytes. The raw bytes are used in {@link
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * #equals(Object o) equals()} and {@link
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * #compareTo(KernelStackRecord r) compareTo()} to test equality and
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * to determine the natural ordering of kernel stack records.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @return the native DTrace library's internal representation of
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * this record's stack as a non-null array of bytes
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public byte[]
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Gets the raw bytes used to represent this record's stack value in
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * the native DTrace library. To get a human-readable
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * representation, call {@link #toString()}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @return {@link #getRawStackData()}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Compares the specified object with this {@code KernelStackRecord}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * for equality. Returns {@code true} if and only if the specified
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * object is also a {@code KernelStackRecord} and both records have
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * the same raw stack data.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * This implementation first checks if the specified object is this
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code KernelStackRecord}. If so, it returns {@code true}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @return {@code true} if and only if the specified object is also
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * a {@code KernelStackRecord} and both records have the same raw
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * stack data
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public boolean
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (o == this) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return true;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (o instanceof KernelStackRecord) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return false;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Overridden to ensure that equal instances have equal hash codes.
127bbe13a6d36580af6a8ded154f1201a6250772tomee * Compares this record with the given {@code KernelStackRecord}.
127bbe13a6d36580af6a8ded154f1201a6250772tomee * Compares the first unequal pair of bytes at the same index in
127bbe13a6d36580af6a8ded154f1201a6250772tomee * each record's raw stack data, or if all corresponding bytes are
127bbe13a6d36580af6a8ded154f1201a6250772tomee * equal, compares the length of each record's array of raw stack
127bbe13a6d36580af6a8ded154f1201a6250772tomee * data. Corresponding bytes are compared as unsigned values. The
127bbe13a6d36580af6a8ded154f1201a6250772tomee * {@code compareTo()} method is compatible with {@link
127bbe13a6d36580af6a8ded154f1201a6250772tomee * #equals(Object o) equals()}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * This implementation first checks if the specified record is this
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code KernelStackRecord}. If so, it returns {@code 0}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @return -1, 0, or 1 as this record's raw stack data is less than,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * equal to, or greater than the given record's raw stack data.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (r == this) {
127bbe13a6d36580af6a8ded154f1201a6250772tomee return ProbeData.compareByteArrays(rawStackData, r.rawStackData);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee private void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // Make a defensive copy of stack frames and raw bytes
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // check class invariants
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } catch (Exception e) {
4ae67516a1d5dc4a5dbc761762bad5b596647388tomee InvalidObjectException x = new InvalidObjectException(
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Gets a multi-line string representation of a stack with one frame
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * per line. Each line is of the format {@code
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * module`function+offset}, where {@code module} and {@code
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * function} are symbol names and offset is a hex integer preceded
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * by {@code 0x}. For example: {@code genunix`open+0x19}. The
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * offset (and the preceding '+' sign) are omitted if offset is
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * zero. If function name lookup fails, the raw pointer value is
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * used instead. In that case, the module name (and the `
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * delimiter) may or may not be present, depending on whether or not
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * module lookup also fails, and a raw pointer value appears in
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * place of {@code function+offset} as a hex value preceded by
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code 0x}. The format just described, not including surrounding
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * whitespce, is defined in the native DTrace library and is as
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * stable as that library definition. Each line is indented by an
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * equal (unspecified) number of spaces.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * If human-readable stack frames are not available (see {@link
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * #getStackFrames()}), a table represenation of {@link
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * #getRawStackData()} is returned instead. The table displays 16
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * bytes per row in unsigned hex followed by the ASCII character
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * representations of those bytes. Each unprintable character is
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * represented by a period (.).