use std::fmt;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub enum JvmError {
ParseError(ParseError),
RuntimeError(RuntimeError),
MemoryError(MemoryError),
ClassLoadingError(ClassLoadingError),
NativeError(NativeError),
}
impl fmt::Display for JvmError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
JvmError::ParseError(e) => write!(f, "Parse error: {}", e),
JvmError::RuntimeError(e) => write!(f, "Runtime error: {}", e),
JvmError::MemoryError(e) => write!(f, "Memory error: {}", e),
JvmError::ClassLoadingError(e) => write!(f, "Class loading error: {}", e),
JvmError::NativeError(e) => write!(f, "Native error: {}", e),
}
}
}
impl std::error::Error for JvmError {}
impl From<String> for JvmError {
fn from(err: String) -> Self {
JvmError::RuntimeError(RuntimeError::Unimplemented(err))
}
}
impl From<&str> for JvmError {
fn from(err: &str) -> Self {
JvmError::RuntimeError(RuntimeError::Unimplemented(err.to_string()))
}
}
impl From<RuntimeError> for JvmError {
fn from(err: RuntimeError) -> Self {
JvmError::RuntimeError(err)
}
}
impl From<MemoryError> for JvmError {
fn from(err: MemoryError) -> Self {
JvmError::MemoryError(err)
}
}
impl From<ClassLoadingError> for JvmError {
fn from(err: ClassLoadingError) -> Self {
JvmError::ClassLoadingError(err)
}
}
impl From<ParseError> for JvmError {
fn from(err: ParseError) -> Self {
JvmError::ParseError(err)
}
}
impl From<NativeError> for JvmError {
fn from(err: NativeError) -> Self {
JvmError::NativeError(err)
}
}
#[derive(Debug, Clone)]
pub enum ParseError {
InvalidMagic(u32),
UnsupportedVersion(u16, u16),
InvalidConstantPoolTag(u8),
InvalidAttributeLength,
InvalidUtf8String,
InvalidMethodDescriptor(String),
InvalidFieldDescriptor(String),
InvalidOpcode(u8),
InvalidBytecode(String),
IoError(Arc<dyn std::error::Error>),
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParseError::InvalidMagic(magic) => write!(
f,
"Invalid magic number: 0x{:08X} (expected 0xCAFEBABE)",
magic
),
ParseError::UnsupportedVersion(major, minor) => {
write!(f, "Unsupported class file version: {}.{}", major, minor)
}
ParseError::InvalidConstantPoolTag(tag) => {
write!(f, "Invalid constant pool tag: {}", tag)
}
ParseError::InvalidAttributeLength => write!(f, "Invalid attribute length"),
ParseError::InvalidUtf8String => write!(f, "Invalid UTF-8 string in constant pool"),
ParseError::InvalidMethodDescriptor(desc) => {
write!(f, "Invalid method descriptor: {}", desc)
}
ParseError::InvalidFieldDescriptor(desc) => {
write!(f, "Invalid field descriptor: {}", desc)
}
ParseError::InvalidOpcode(opcode) => write!(f, "Invalid opcode: 0x{:02X}", opcode),
ParseError::InvalidBytecode(msg) => write!(f, "Invalid bytecode: {}", msg),
ParseError::IoError(e) => write!(f, "IO error: {}", e),
}
}
}
impl From<std::io::Error> for ParseError {
fn from(err: std::io::Error) -> Self {
ParseError::IoError(Arc::new(err))
}
}
#[derive(Debug, Clone)]
pub enum RuntimeError {
StackUnderflow,
StackOverflow,
LocalVariableOutOfBounds(usize),
ArrayIndexOutOfBounds(usize, usize),
NullPointerException,
DivisionByZero,
ClassNotFound(String),
MethodNotFound(String, String),
FieldNotFound(String, String),
InvalidTypeConversion(String, String),
UnsupportedOperation(String),
ArithmeticOverflow,
InvalidReference(u32),
InvalidArrayType(String),
InvalidArrayLength(usize),
InvalidMonitorState,
IllegalMonitorState,
IllegalArgument(String),
IllegalState(String),
Unimplemented(String),
InvalidOpcode(u8),
ExceptionThrown(String),
ClassCastException(String, String),
ArrayStoreException,
NegativeArraySizeException(i32),
IllegalAccessException(String),
InstantiationException(String),
StringIndexOutOfBounds(usize, usize),
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RuntimeError::StackUnderflow => write!(f, "Stack underflow"),
RuntimeError::StackOverflow => write!(f, "Stack overflow"),
RuntimeError::LocalVariableOutOfBounds(index) => {
write!(f, "Local variable index {} out of bounds", index)
}
RuntimeError::ArrayIndexOutOfBounds(index, length) => write!(
f,
"Array index {} out of bounds (length: {})",
index, length
),
RuntimeError::NullPointerException => write!(f, "Null pointer exception"),
RuntimeError::DivisionByZero => write!(f, "Division by zero"),
RuntimeError::ClassNotFound(name) => write!(f, "Class not found: {}", name),
RuntimeError::MethodNotFound(class, method) => {
write!(f, "Method {} not found in class {}", method, class)
}
RuntimeError::FieldNotFound(class, field) => {
write!(f, "Field {} not found in class {}", field, class)
}
RuntimeError::InvalidTypeConversion(from, to) => {
write!(f, "Invalid type conversion from {} to {}", from, to)
}
RuntimeError::UnsupportedOperation(op) => write!(f, "Unsupported operation: {}", op),
RuntimeError::ArithmeticOverflow => write!(f, "Arithmetic overflow"),
RuntimeError::InvalidReference(addr) => write!(f, "Invalid object reference: {}", addr),
RuntimeError::InvalidArrayType(ty) => write!(f, "Invalid array type: {}", ty),
RuntimeError::InvalidArrayLength(len) => write!(f, "Invalid array length: {}", len),
RuntimeError::InvalidMonitorState => write!(f, "Invalid monitor state"),
RuntimeError::IllegalMonitorState => write!(f, "Illegal monitor state"),
RuntimeError::IllegalArgument(msg) => write!(f, "Illegal argument: {}", msg),
RuntimeError::IllegalState(msg) => write!(f, "Illegal state: {}", msg),
RuntimeError::Unimplemented(feature) => write!(f, "Unimplemented feature: {}", feature),
RuntimeError::InvalidOpcode(opcode) => write!(f, "Invalid opcode: 0x{:02X}", opcode),
RuntimeError::ExceptionThrown(msg) => write!(f, "Exception thrown: {}", msg),
RuntimeError::ClassCastException(from, to) => write!(
f,
"Class cast exception: cannot cast from {} to {}",
from, to
),
RuntimeError::ArrayStoreException => write!(f, "Array store exception"),
RuntimeError::NegativeArraySizeException(size) => {
write!(f, "Negative array size exception: {}", size)
}
RuntimeError::IllegalAccessException(msg) => {
write!(f, "Illegal access exception: {}", msg)
}
RuntimeError::InstantiationException(msg) => {
write!(f, "Instantiation exception: {}", msg)
}
RuntimeError::StringIndexOutOfBounds(index, length) => write!(
f,
"String index {} out of bounds (length: {})",
index, length
),
}
}
}
#[derive(Debug, Clone)]
pub enum MemoryError {
OutOfMemory,
InvalidHeapAddress(u32),
InvalidReference(u32),
InvalidMonitorState,
IllegalMonitorState,
HeapCorruption,
GcError(String),
MemoryLimitExceeded(usize),
InvalidObjectHeader,
InvalidArrayHeader,
AllocationFailed(String),
InvalidArrayLength(usize),
InvalidArrayType(String),
ArrayIndexOutOfBounds(usize, usize), InvalidArrayOperation(String),
CompressedOopsOverflow(u32),
}
impl fmt::Display for MemoryError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MemoryError::OutOfMemory => write!(f, "Out of memory"),
MemoryError::InvalidHeapAddress(addr) => write!(f, "Invalid heap address: {}", addr),
MemoryError::InvalidReference(addr) => write!(f, "Invalid object reference: {}", addr),
MemoryError::InvalidMonitorState => write!(f, "Invalid monitor state"),
MemoryError::IllegalMonitorState => write!(f, "Illegal monitor state"),
MemoryError::HeapCorruption => write!(f, "Heap corruption detected"),
MemoryError::GcError(msg) => write!(f, "Garbage collection error: {}", msg),
MemoryError::MemoryLimitExceeded(limit) => {
write!(f, "Memory limit exceeded: {} bytes", limit)
}
MemoryError::InvalidObjectHeader => write!(f, "Invalid object header"),
MemoryError::InvalidArrayHeader => write!(f, "Invalid array header"),
MemoryError::AllocationFailed(msg) => write!(f, "Memory allocation failed: {}", msg),
MemoryError::InvalidArrayLength(len) => write!(f, "Invalid array length: {}", len),
MemoryError::InvalidArrayType(ty) => write!(f, "Invalid array type: {}", ty),
MemoryError::ArrayIndexOutOfBounds(index, length) => write!(
f,
"Array index {} out of bounds (length: {})",
index, length
),
MemoryError::InvalidArrayOperation(msg) => {
write!(f, "Invalid array operation: {}", msg)
}
MemoryError::CompressedOopsOverflow(addr) => write!(
f,
"Compressed oops overflow: handle {} does not fit in 16-bit compressed space",
addr
),
}
}
}
impl From<MemoryError> for RuntimeError {
fn from(err: MemoryError) -> Self {
match err {
MemoryError::InvalidMonitorState => RuntimeError::InvalidMonitorState,
MemoryError::IllegalMonitorState => RuntimeError::IllegalMonitorState,
MemoryError::InvalidReference(addr) => RuntimeError::InvalidReference(addr),
_ => RuntimeError::Unimplemented(err.to_string()),
}
}
}
#[derive(Debug, Clone)]
pub enum ClassLoadingError {
ClassFileNotFound(String),
ClassFormatError(String),
ClassCircularityError(String),
NoClassDefFound(String),
UnsupportedClassVersion(String, u16, u16),
VerificationFailed(String),
LinkageError(String),
IllegalAccessError(String),
InstantiationError(String),
ClassLoaderConstraintViolation(String),
}
impl fmt::Display for ClassLoadingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ClassLoadingError::ClassFileNotFound(name) => {
write!(f, "Class file not found: {}", name)
}
ClassLoadingError::ClassFormatError(msg) => write!(f, "Class format error: {}", msg),
ClassLoadingError::ClassCircularityError(name) => {
write!(f, "Class circularity error: {}", name)
}
ClassLoadingError::NoClassDefFound(name) => {
write!(f, "No class definition found: {}", name)
}
ClassLoadingError::UnsupportedClassVersion(name, major, minor) => write!(
f,
"Unsupported class version for {}: {}.{}",
name, major, minor
),
ClassLoadingError::VerificationFailed(msg) => {
write!(f, "Class verification failed: {}", msg)
}
ClassLoadingError::LinkageError(msg) => write!(f, "Linkage error: {}", msg),
ClassLoadingError::IllegalAccessError(msg) => {
write!(f, "Illegal access error: {}", msg)
}
ClassLoadingError::InstantiationError(msg) => write!(f, "Instantiation error: {}", msg),
ClassLoadingError::ClassLoaderConstraintViolation(msg) => {
write!(f, "Class loader constraint violation: {}", msg)
}
}
}
}
#[derive(Debug, Clone)]
pub enum NativeError {
NativeMethodNotFound(String, String),
NativeMethodFailed(String, String),
NativeLibraryNotFound(String),
NativeLibraryLoadFailed(String),
UnsatisfiedLinkError(String),
NativeMethodSignatureMismatch(String),
}
impl fmt::Display for NativeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
NativeError::NativeMethodNotFound(class, method) => {
write!(f, "Native method {}.{} not found", class, method)
}
NativeError::NativeMethodFailed(class, method) => {
write!(f, "Native method {}.{} failed", class, method)
}
NativeError::NativeLibraryNotFound(lib) => {
write!(f, "Native library not found: {}", lib)
}
NativeError::NativeLibraryLoadFailed(lib) => {
write!(f, "Native library load failed: {}", lib)
}
NativeError::UnsatisfiedLinkError(msg) => write!(f, "Unsatisfied link error: {}", msg),
NativeError::NativeMethodSignatureMismatch(msg) => {
write!(f, "Native method signature mismatch: {}", msg)
}
}
}
}
pub type JvmResult<T> = Result<T, JvmError>;
pub type InterpreterResult = Result<(), JvmError>;
pub type ClassFileResult<T> = Result<T, JvmError>;
pub type MemoryResult<T> = Result<T, JvmError>;
pub fn to_runtime_error<T: ToString>(msg: T) -> JvmError {
JvmError::RuntimeError(RuntimeError::Unimplemented(msg.to_string()))
}
pub fn to_parse_error<T: Into<ParseError>>(err: T) -> JvmError {
JvmError::ParseError(err.into())
}
pub fn to_runtime_error_enum<T: Into<RuntimeError>>(err: T) -> JvmError {
JvmError::RuntimeError(err.into())
}
pub fn to_memory_error<T: Into<MemoryError>>(err: T) -> JvmError {
JvmError::MemoryError(err.into())
}
pub fn to_class_loading_error<T: Into<ClassLoadingError>>(err: T) -> JvmError {
JvmError::ClassLoadingError(err.into())
}
pub trait ToJvmError<T> {
fn to_jvm_error(self) -> JvmError;
}
impl ToJvmError<ParseError> for ParseError {
fn to_jvm_error(self) -> JvmError {
JvmError::ParseError(self)
}
}
impl ToJvmError<RuntimeError> for RuntimeError {
fn to_jvm_error(self) -> JvmError {
JvmError::RuntimeError(self)
}
}
impl ToJvmError<MemoryError> for MemoryError {
fn to_jvm_error(self) -> JvmError {
JvmError::MemoryError(self)
}
}
impl ToJvmError<ClassLoadingError> for ClassLoadingError {
fn to_jvm_error(self) -> JvmError {
JvmError::ClassLoadingError(self)
}
}
impl ToJvmError<String> for String {
fn to_jvm_error(self) -> JvmError {
JvmError::RuntimeError(RuntimeError::Unimplemented(self))
}
}
impl ToJvmError<&str> for &str {
fn to_jvm_error(self) -> JvmError {
JvmError::RuntimeError(RuntimeError::Unimplemented(self.to_string()))
}
}
#[macro_export]
macro_rules! convert_result {
($expr:expr) => {
$expr.map_err(|e| e.to_jvm_error())
};
}