/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package java.lang;
import org.jikesrvm.VM;
import org.jikesrvm.runtime.StackTrace;
import org.jikesrvm.scheduler.RVMThread;
/**
* Implementation of throwables for JikesRVM.
*/
public final class VMThrowable {
/** The stack trace for this throwable */
private final StackTrace stackTrace;
/**
* Zero length array of stack trace elements, returned when handling an OOM or
* an unexpected error
*/
private static final StackTraceElement[] zeroLengthStackTrace = new StackTraceElement[0];
/** Constructor called by fillInStackTrace*/
private VMThrowable(StackTrace stackTrace) {
this.stackTrace = stackTrace;
}
/**
* Create the VMThrowable
* @return constructed VMThrowable
*/
static VMThrowable fillInStackTrace(Throwable parent) {
if (!VM.fullyBooted) {
return null;
} else if (RVMThread.getCurrentThread().isCollectorThread()) {
VM.sysWriteln("Exception in GC thread");
RVMThread.dumpVirtualMachine();
return null;
}
try {
StackTrace stackTrace = new StackTrace();
return new VMThrowable(stackTrace);
} catch (OutOfMemoryError oome) {
return null;
} catch (Throwable t) {
VM.sysFail("VMThrowable.fillInStackTrace(): Cannot fill in a stack trace; got a weird Throwable when I tried to");
return null;
}
}
/** Return the stack trace */
StackTraceElement[] getStackTrace(Throwable parent) {
if (stackTrace == null) {
return zeroLengthStackTrace;
} else if (RVMThread.getCurrentThread().isCollectorThread()) {
VM.sysWriteln("VMThrowable.getStackTrace called from GC thread: dumping stack using scheduler");
RVMThread.dumpStack();
return zeroLengthStackTrace;
}
StackTrace.Element[] vmElements;
try {
vmElements = stackTrace.getStackTrace(parent);
} catch (Throwable t) {
VM.sysWriteln("Error calling StackTrace.getStackTrace: dumping stack using scheduler");
RVMThread.dumpStack();
return zeroLengthStackTrace;
}
if (vmElements == null) {
VM.sysWriteln("Error calling StackTrace.getStackTrace returned null");
RVMThread.dumpStack();
return zeroLengthStackTrace;
}
if (VM.fullyBooted) {
try {
return JikesRVMStackTraceSupport.convertToJavaClassLibraryStackTrace(vmElements);
} catch (Throwable t) {
VM.sysWriteln("Error constructing StackTraceElements: dumping stack");
}
} else {
VM.sysWriteln("Dumping stack using sysWrite in not fullyBooted VM");
}
for (StackTrace.Element vmElement : vmElements) {
if (vmElement == null) {
VM.sysWriteln("Error stack trace with null entry");
RVMThread.dumpStack();
return zeroLengthStackTrace;
}
String fileName = vmElement.getFileName();
int lineNumber = vmElement.getLineNumber();
String className = vmElement.getClassName();
String methodName = vmElement.getMethodName();
VM.sysWrite(" at ");
if (!className.isEmpty()) {
VM.sysWrite(className);
VM.sysWrite(".");
}
VM.sysWrite(methodName);
if (fileName != null) {
VM.sysWrite("(");
VM.sysWrite(fileName);
if (lineNumber > 0) {
VM.sysWrite(":");
VM.sysWrite(vmElement.getLineNumber());
}
VM.sysWrite(")");
}
VM.sysWriteln();
}
return zeroLengthStackTrace;
}
}