fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER START
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * or http://www.opensolaris.org/os/licensing.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * See the License for the specific language governing permissions
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * and limitations under the License.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * CDDL HEADER END
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/*
e77b06d21580f630e0a7c437495ab283d3672828tomee * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Use is subject to license terms.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * ident "%Z%%M% %I% %E% SMI"
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeepackage org.opensolaris.os.dtrace;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeimport java.util.*;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeimport java.io.*;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeimport java.util.regex.Pattern;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeeimport java.beans.*;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee/**
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * A value generated by the DTrace {@code stack()} action.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * <p>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Immutable. Supports persistence using {@link java.beans.XMLEncoder}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @author Tom Erickson
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomeepublic final class KernelStackRecord implements StackValueRecord,
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee Serializable, Comparable <KernelStackRecord>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee{
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static final long serialVersionUID = 8616454544771346573L;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static final int STACK_INDENT = 14;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static final StackFrame[] EMPTY_FRAMES = new StackFrame[] {};
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee try {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee BeanInfo info = Introspector.getBeanInfo(KernelStackRecord.class);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee PersistenceDelegate persistenceDelegate =
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee new DefaultPersistenceDelegate(
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee new String[] {"stackFrames", "rawStackData"})
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /*
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Need to prevent DefaultPersistenceDelegate from using
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * overridden equals() method, resulting in a
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * StackOverFlowError. Revert to PersistenceDelegate
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * implementation. See
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * http://forum.java.sun.com/thread.jspa?threadID=
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * 477019&tstart=135
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee protected boolean
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee mutatesTo(Object oldInstance, Object newInstance)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return (newInstance != null && oldInstance != null &&
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee oldInstance.getClass() == newInstance.getClass());
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee };
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee BeanDescriptor d = info.getBeanDescriptor();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee d.setValue("persistenceDelegate", persistenceDelegate);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } catch (IntrospectionException e) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee System.out.println(e);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static final Pattern STACK_TOKENIZER = Pattern.compile("\\s*\n\\s*");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Called by JNI layer to convert a stack formatted by the native
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * DTrace library into an unformatted array of stack frames.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee static StackFrame[]
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee parse(String s)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee //
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // First trim the leading whitespace to avoid an initial empty
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // element in the returned array.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee //
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee s = s.trim();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee StackFrame[] frames;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (s.length() == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee frames = EMPTY_FRAMES;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } else {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee String[] f = STACK_TOKENIZER.split(s);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee int n = f.length;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee frames = new StackFrame[n];
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (int i = 0; i < n; ++i) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee frames[i] = new StackFrame(f[i]);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return frames;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /** @serial */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee private StackFrame[] stackFrames;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /** @serial */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee private byte[] rawStackData;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Called by native code and by UserStackRecord (in its constructor
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * called by native code).
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @throws NullPointerException if rawBytes is {@code null}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee KernelStackRecord(byte[] rawBytes)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // No need for defensive copy; native code will not modify input
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // raw bytes.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee rawStackData = rawBytes;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (rawStackData == null) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee throw new NullPointerException("raw stack data is null");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Creates a {@code KernelStackRecord} with the given stack frames
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * and raw stack data. Supports XML persistence.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee KernelStackRecord(StackFrame[] frames, byte[] rawBytes)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (frames != null) {
e77b06d21580f630e0a7c437495ab283d3672828tomee stackFrames = frames.clone();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (rawBytes != null) {
e77b06d21580f630e0a7c437495ab283d3672828tomee rawStackData = rawBytes.clone();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee validate();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
91cfa10a8e55050a5103c4b2e83b0bf8d783a7cbtomee private final void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee validate()
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (rawStackData == null) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee throw new NullPointerException("raw stack data is null");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // stackFrames may be null; if non-null, cannot contain null
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // elements
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (stackFrames != null) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (StackFrame f : stackFrames) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (f == null) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee throw new NullPointerException("stack frame is null");
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public StackFrame[]
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee getStackFrames()
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (stackFrames == null) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return EMPTY_FRAMES;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
e77b06d21580f630e0a7c437495ab283d3672828tomee return stackFrames.clone();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Called by native code and by UserStackRecord in its
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * setStackFrames() method.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee setStackFrames(StackFrame[] frames)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // No need for defensive copy; native code will not modify input
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // frames.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee stackFrames = frames;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee validate();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
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 *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @return the native DTrace library's internal representation of
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * this record's stack as a non-null array of bytes
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public byte[]
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee getRawStackData()
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
e77b06d21580f630e0a7c437495ab283d3672828tomee return rawStackData.clone();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
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 *
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * @return {@link #getRawStackData()}
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public Object
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee getValue()
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
e77b06d21580f630e0a7c437495ab283d3672828tomee return rawStackData.clone();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public List <StackFrame>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee asList()
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (stackFrames == null) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return Collections. <StackFrame> emptyList();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
e77b06d21580f630e0a7c437495ab283d3672828tomee return Collections. <StackFrame> unmodifiableList(
e77b06d21580f630e0a7c437495ab283d3672828tomee Arrays.asList(stackFrames));
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
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 * <p>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * This implementation first checks if the specified object is this
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code KernelStackRecord}. If so, it returns {@code true}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee @Override
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public boolean
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee equals(Object o)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (o == this) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return true;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (o instanceof KernelStackRecord) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee KernelStackRecord r = (KernelStackRecord)o;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return Arrays.equals(rawStackData, r.rawStackData);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return false;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * Overridden to ensure that equal instances have equal hash codes.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee @Override
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public int
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee hashCode()
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return Arrays.hashCode(rawStackData);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
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 * <p>
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * This implementation first checks if the specified record is this
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee * {@code KernelStackRecord}. If so, it returns {@code 0}.
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee *
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 */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public int
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee compareTo(KernelStackRecord r)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (r == this) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return 0;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
127bbe13a6d36580af6a8ded154f1201a6250772tomee return ProbeData.compareByteArrays(rawStackData, r.rawStackData);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee private void
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee readObject(ObjectInputStream s)
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee throws IOException, ClassNotFoundException
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee s.defaultReadObject();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // Make a defensive copy of stack frames and raw bytes
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (stackFrames != null) {
e77b06d21580f630e0a7c437495ab283d3672828tomee stackFrames = stackFrames.clone();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (rawStackData != null) {
e77b06d21580f630e0a7c437495ab283d3672828tomee rawStackData = rawStackData.clone();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee // check class invariants
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee try {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee validate();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee } catch (Exception e) {
4ae67516a1d5dc4a5dbc761762bad5b596647388tomee InvalidObjectException x = new InvalidObjectException(
4ae67516a1d5dc4a5dbc761762bad5b596647388tomee e.getMessage());
4ae67516a1d5dc4a5dbc761762bad5b596647388tomee x.initCause(e);
4ae67516a1d5dc4a5dbc761762bad5b596647388tomee throw x;
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee /**
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 * <p>
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 (.).
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee */
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee @Override
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee public String
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee toString()
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee StackFrame[] frames = getStackFrames();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee if (frames.length == 0) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return ScalarRecord.rawBytesString(rawStackData);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee
4ae67516a1d5dc4a5dbc761762bad5b596647388tomee StringBuilder buf = new StringBuilder();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee buf.append('\n');
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (StackFrame f : frames) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee for (int i = 0; i < STACK_INDENT; ++i) {
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee buf.append(' ');
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee buf.append(f);
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee buf.append('\n');
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee return buf.toString();
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee }
fb3fb4f3d76d55b64440afd0af72775dfad3bd1dtomee}