/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * ident "%Z%%M% %I% %E% SMI" */ package org.opensolaris.os.dtrace; import java.util.*; import java.io.*; import java.beans.*; /** * A value generated by the DTrace {@code ustack()} or {@code jstack()} * action. *
* Immutable. Supports persistence using {@link java.beans.XMLEncoder}.
*
* @author Tom Erickson
*/
public final class UserStackRecord implements StackValueRecord,
Serializable, Comparable
* This implementation first checks if the specified object is this
* {@code UserStackRecord}. If so, it returns {@code true}.
*
* @return {@code true} if and only if the specified object is also
* a {@code UserStackRecord} and both stacks have the same raw stack
* data (including process ID)
*/
@Override
public boolean
equals(Object o)
{
if (o == this) {
return true;
}
if (o instanceof UserStackRecord) {
UserStackRecord r = (UserStackRecord)o;
return stackRecord.equals(r.stackRecord);
}
return false;
}
/**
* Overridden to ensure that equal instances have equal hash codes.
*/
@Override
public int
hashCode()
{
return stackRecord.hashCode();
}
/**
* Compares this record with the given {@code UserStackRecord}.
* Compares the first unequal pair of bytes at the same index in
* each record's raw stack data, or if all corresponding bytes are
* equal, compares the length of each record's array of raw stack
* data. Corresponding bytes are compared as unsigned values. The
* {@code compareTo()} method is compatible with {@link
* #equals(Object o) equals()}.
*
* This implementation first checks if the specified object is this
* {@code UserStackRecord}. If so, it returns {@code 0}.
*
* @return -1, 0, or 1 as this record's raw stack data is less than,
* equal to, or greater than the given record's raw stack data
*/
public int
compareTo(UserStackRecord r)
{
if (r == this) {
return 0;
}
return stackRecord.compareTo(r.stackRecord);
}
/**
* Serialize this {@code UserStackRecord} instance.
*
* @serialData Serialized fields are emitted, followed first by this
* record's stack frames as an array of type {@link String}, then by
* this record's raw stack data as an array of bytes.
*/
private void
writeObject(ObjectOutputStream s) throws IOException
{
s.defaultWriteObject();
s.writeObject(stackRecord.getStackFrames());
s.writeObject(stackRecord.getRawStackData());
}
private void
readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
{
s.defaultReadObject();
try {
StackFrame[] frames = (StackFrame[])s.readObject();
byte[] rawBytes = (byte[])s.readObject();
// defensively copies stack frames and raw bytes
stackRecord = new KernelStackRecord(frames, rawBytes);
} catch (Exception e) {
InvalidObjectException x = new InvalidObjectException(
e.getMessage());
x.initCause(e);
throw x;
}
// check class invariants
try {
validate();
} catch (Exception e) {
InvalidObjectException x = new InvalidObjectException(
e.getMessage());
x.initCause(e);
throw x;
}
}
/**
* Gets the {@link KernelStackRecord#toString() string
* representation} of the view returned by {@link
* #asKernelStackRecord()} preceded by the user process ID on its
* own line. The process ID is in the format {@code process ID:
* pid} (where pid is a decimal integer) and is indented by
* the same number of spaces as the stack frames. The exact format
* is subject to change.
*/
public String
toString()
{
StringBuilder buf = new StringBuilder();
final int stackindent = KernelStackRecord.STACK_INDENT;
int i;
buf.append('\n');
for (i = 0; i < KernelStackRecord.STACK_INDENT; ++i) {
buf.append(' ');
}
buf.append("process ID: ");
buf.append(processID);
buf.append(stackRecord.toString()); // starts with newline
return buf.toString();
}
}