vmstackreader.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 221 行

JAVA
221
字号
/*
 * $Id: VmStackReader.java,v 1.7 2004/02/26 10:33:48 epr Exp $
 */
package org.jnode.vm;

import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.classmgr.VmType;

/**
 * Abstract class for reading information from stack frames.
 * 
 * @author Ewout Prangsma (epr@users.sourceforge.net)
 */
public abstract class VmStackReader extends VmSystemObject {

	/**
	 * Gets the previous frame (if any)
	 * @param sf The stackframe to get the previous frame from.
	 * @return The previous frame or null.
	 */
	final Address getPrevious(Address sf) {
		if (isValid(sf)) {
			return Unsafe.getAddress(sf, getPreviousOffset(sf));
		} else {
			return null;
		}
	}

	/**
	 * Gets the method of a given stackframe.
	 * @param sf Stackframe pointer
	 * @return The method
	 */
	final VmMethod getMethod(Address sf) {
		return (VmMethod)Unsafe.getObject(sf, getMethodOffset(sf));
	}

	/**
	 * Gets the java program counter of a given stackframe.
	 * @param sf Stackframe pointer
	 * @return the pc
	 */
	final int getPC(Address sf) {
		return Unsafe.getInt(sf, getPCOffset(sf));
	}

	/**
	 * Sets the java program counter of a given stackframe.
	 * @param sf Stackframe pointer
	 * @param pc
	 */
	final void setPC(Address sf, int pc) {
		Unsafe.setInt(sf, getPCOffset(sf), pc);
	}

	/**
	 * Gets the magic constant of a given stackframe.
	 * @param sf Stackframe pointer
	 * @return The magic
	 */
	final int getMagic(Address sf) {
		return Unsafe.getInt(sf, getMagicOffset(sf));
	}

	/**
	 * Gets the return address of a given stackframe.
	 * @param sf Stackframe pointer
	 * @return The address
	 */
	final Address getReturnAddress(Address sf) {
		return Unsafe.getAddress(sf, getReturnAddressOffset(sf));
	}

	/**
	 * Is a given stackframe valid?
	 * @param sf
	 * @return boolean
	 */
	final boolean isValid(Address sf) {
		if (sf == null) {
			return false;
		}
		if (getMethod(sf) == null) {
			return false;
		}
		final int magic = getMagic(sf) & VmStackFrame.MAGIC_MASK;
		if ((magic != VmStackFrame.MAGIC_COMPILED) && (magic != VmStackFrame.MAGIC_INTERPRETED)) {
			return false;
		}
		return true;
	}

	/**
	 * Is the given frame a bottom of stack marker?
	 * @param sf
	 * @return boolean
	 */
	final boolean isStackBottom(Address sf) {
		if (sf == null) {
			return true;
		}
		return (getMethod(sf) == null)
			&& (getMagic(sf) == 0)
			&& (getPrevious(sf) == null);
	}

	/**
	 * Gets the stacktrace for a given current frame.
	 * @param argFrame
	 * @param ip The instruction pointer of the given frame
	 * @param limit Maximum length of returned array.
	 * @return VmStackFrame[]
	 */
	final VmStackFrame[] getVmStackTrace(Address argFrame, Address ip, int limit) {

		final Address frame = argFrame;
		Address f = frame;
		int count = 0;
		while (isValid(f) && (count < limit)) {
			count++;
			f = getPrevious(f);
		}
		if ((f != null) && !isStackBottom(f) && (count < limit)) {
			Unsafe.debug("Corrupted stack!, st.length=");
			Unsafe.debug(count);
			Unsafe.debug(" f.magic=");
			Unsafe.debug(getMagic(f));
			//Unsafe.die();
		}

		final VmStackFrame[] stack = new VmStackFrame[count];
		f = frame;
		for (int i = 0; i < count; i++) {
			stack[i] = new VmStackFrame(f, this, ip);
			ip = stack[i].getReturnAddress();
			f = getPrevious(f);
		}

		return stack;
	}

	/**
	 * Count the number of stackframe from a given frame.
	 * @param sf
	 * @return int
	 */
	final int countStackFrames(Address sf) {
		int count = 0;
		while (isValid(sf)) {
			count++;
			sf = getPrevious(sf);
		}
		return count;
	}

	/**
	 * Show the current stacktrace using Screen.debug.
	 */	
	public final void debugStackTrace() {
		Address f = Unsafe.getCurrentFrame();
		Unsafe.debug("Debug stacktrace: ");
		boolean first = true;
		int max = 20;
		while (isValid(f) && (max > 0)) {
			if (first) {
				first = false;
			} else {
				Unsafe.debug(", ");
			}
			final VmMethod method = getMethod(f);
			final int pc = getPC(f);
			final int lineNr = method.getBytecode().getLineNr(pc);
			final VmType vmClass = method.getDeclaringClass();
			Unsafe.debug(vmClass.getName());
			Unsafe.debug("::");
			Unsafe.debug(method.getName()); 
			Unsafe.debug(lineNr);
			f = getPrevious(f);
			max--;
		}
		if (isValid(f)) {
		    Unsafe.debug("...");
		}
	}
	
	/**
	 * Gets the offset within the frame of previous frame (if any)
	 * @param sf The stackframe to get the previous frame from.
	 * @return The previous frame or null.
	 */
	protected abstract int getPreviousOffset(Address sf);

	/**
	 * Gets the offset within the stackframe of method.
	 * @param sf Stackframe pointer
	 * @return The method offset
	 */
	protected abstract int getMethodOffset(Address sf);

	/**
	 * Gets the offset within the stackframe of java program counter.
	 * @param sf Stackframe pointer
	 * @return The pc offset
	 */
	protected abstract int getPCOffset(Address sf);

	/**
	 * Gets the offset within the stackframe of the magic constant.
	 * @param sf Stackframe pointer
	 * @return The magic offset
	 */
	protected abstract int getMagicOffset(Address sf);

	/**
	 * Gets the offset within the stackframe of the return address.
	 * @param sf Stackframe pointer
	 * @return The return address offset
	 */
	protected abstract int getReturnAddressOffset(Address sf);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?