From 48d8db8e9ee89ade00a4ee009e2eee780ca4ae55 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 11 Jan 2025 01:08:18 -0600 Subject: [PATCH] execute: implement runtime exceptions --- Makefile | 2 +- c/execute.c | 164 +++++++++-- c/frame.c | 1 - c/hash_table.c | 4 - c/native_types.h | 1 + classes/java/lang/ArithmeticException.java | 4 + .../lang/ArrayIndexOutOfBoundsException.java | 4 + classes/java/lang/ArrayStoreException.java | 4 + classes/java/lang/Backtrace.java | 2 + classes/java/lang/ClassCastException.java | 4 + classes/java/lang/Error.java | 4 + .../java/lang/IndexOutOfBoundsException.java | 4 + .../java/lang/NegativeArraySizeException.java | 4 + classes/java/lang/NullPointerException.java | 4 + classes/java/lang/RuntimeException.java | 4 + classes/java/lang/StringBuilder.java | 6 +- classes/test/TestRuntimeException.java | 260 ++++++++++++++++++ 17 files changed, 439 insertions(+), 37 deletions(-) create mode 100644 classes/java/lang/ArithmeticException.java create mode 100644 classes/java/lang/ArrayIndexOutOfBoundsException.java create mode 100644 classes/java/lang/ArrayStoreException.java create mode 100644 classes/java/lang/ClassCastException.java create mode 100644 classes/java/lang/Error.java create mode 100644 classes/java/lang/IndexOutOfBoundsException.java create mode 100644 classes/java/lang/NegativeArraySizeException.java create mode 100644 classes/java/lang/NullPointerException.java create mode 100644 classes/java/lang/RuntimeException.java create mode 100644 classes/test/TestRuntimeException.java diff --git a/Makefile b/Makefile index 5704539..e5f3bf1 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protec CFLAGS += -I$(MAKEFILE_PATH)/ CFLAGS += -I$(MAKEFILE_PATH)/c CFLAGS += -DDEBUG -CFLAGS += -DDEBUG_PRINT +#CFLAGS += -DDEBUG_PRINT LDFLAGS = -lm OPT ?= -O0 DEPFLAGS = -MMD -MP diff --git a/c/execute.c b/c/execute.c index 1dff955..a91d193 100644 --- a/c/execute.c +++ b/c/execute.c @@ -9,23 +9,33 @@ #include "native_types_allocate.h" #include "parse_type.h" #include "execute_helper.h" +#include "vm_instance.h" void op_aaload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); uint32_t value = arrayref->u32[index]; operand_stack_push_u32(vm->current_frame, value); } void op_aastore(struct vm * vm) { - uint32_t value = operand_stack_pop_u32(vm->current_frame); + void * ref = operand_stack_pop_ref(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); - arrayref->u32[index] = value; + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); + + arrayref->ref[index] = ref; } void op_aconst_null(struct vm * vm) @@ -72,6 +82,9 @@ void op_anewarray(struct vm * vm, uint32_t index) index); int32_t count = operand_stack_pop_u32(vm->current_frame); + if (count < 0) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NegativeArraySizeException")); + struct arrayref * arrayref = ref_array_allocate(vm, count); assert(arrayref != nullptr); arrayref->class_entry = class_entry; @@ -94,6 +107,8 @@ void op_areturn(struct vm * vm) void op_arraylength(struct vm * vm) { struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); int32_t length = arrayref->length; operand_stack_push_u32(vm->current_frame, length); } @@ -131,6 +146,8 @@ void op_astore_3(struct vm * vm) void op_athrow(struct vm * vm) { struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); + if (objectref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); vm_exception(vm, objectref); } @@ -138,7 +155,11 @@ void op_baload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); int8_t value = arrayref->u8[index]; operand_stack_push_u32(vm->current_frame, value); } @@ -148,7 +169,11 @@ void op_bastore(struct vm * vm) uint8_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); arrayref->u8[index] = value; } @@ -166,7 +191,11 @@ void op_caload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); uint16_t value = arrayref->u16[index]; operand_stack_push_u32(vm->current_frame, value); } @@ -176,7 +205,11 @@ void op_castore(struct vm * vm) uint16_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); arrayref->u16[index] = value; } @@ -190,9 +223,8 @@ void op_checkcast(struct vm * vm, uint32_t index) vm->current_frame->class_entry, index, objectref); - if (!isinstance) { - assert(!"ClassCastException"); - } + if (!isinstance) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ClassCastException")); } } @@ -229,7 +261,11 @@ void op_daload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); uint64_t value = arrayref->u64[index]; operand_stack_push_u64(vm->current_frame, value); } @@ -239,7 +275,11 @@ void op_dastore(struct vm * vm) int64_t value = operand_stack_pop_u64(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); arrayref->u64[index] = value; } @@ -511,7 +551,11 @@ void op_faload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); uint32_t value = arrayref->u32[index]; operand_stack_push_u32(vm->current_frame, value); } @@ -521,7 +565,11 @@ void op_fastore(struct vm * vm) uint32_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); arrayref->u32[index] = value; } @@ -697,7 +745,8 @@ void op_getfield(struct vm * vm, uint32_t index) debugf("getfield instance_index %d\n", field_entry->instance_index); struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); - assert(objectref != nullptr); + if (objectref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); switch (field_descriptor_constant->utf8.bytes[0]) { case 'B': [[fallthrough]]; @@ -723,7 +772,7 @@ void op_getfield(struct vm * vm, uint32_t index) } break; default: - assert(false); + assert(!"invalid field_descriptor_constant"); } } @@ -836,7 +885,11 @@ void op_iaload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); int32_t value = arrayref->u32[index]; operand_stack_push_u32(vm->current_frame, value); } @@ -854,7 +907,11 @@ void op_iastore(struct vm * vm) uint32_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); arrayref->u32[index] = value; } @@ -897,6 +954,8 @@ void op_idiv(struct vm * vm) { int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); + if (value2 == 0) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArithmeticException")); int32_t result = value1 / value2; operand_stack_push_u32(vm->current_frame, result); } @@ -1123,7 +1182,8 @@ void op_invokedynamic(struct vm * vm, uint32_t index) void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count) { struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, count); - assert(objectref != nullptr); + if (objectref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); struct class_entry * class_entry = objectref->class_entry; struct method_entry method_entry = @@ -1138,6 +1198,23 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count) void op_invokespecial(struct vm * vm, uint32_t index) { + struct class_entry * origin_class_entry = vm->current_frame->class_entry; + + struct constant * interfacemethodref_constant = &origin_class_entry->class_file->constant_pool[index - 1]; + assert(interfacemethodref_constant->tag == CONSTANT_Methodref); + struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1]; + assert(nameandtype_constant->tag == CONSTANT_NameAndType); + struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; + assert(method_descriptor_constant->tag == CONSTANT_Utf8); + + uint8_t return_type; + int nargs = descriptor_nargs(method_descriptor_constant, &return_type); + (void)return_type; + + struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, nargs + 1); + if (objectref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + struct method_entry * method_entry = class_resolver_lookup_method_from_methodref_index(vm->class_hash_table.length, vm->class_hash_table.entry, @@ -1178,9 +1255,9 @@ void op_invokevirtual(struct vm * vm, uint32_t index) (void)return_type; struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, nargs + 1); - assert(objectref != nullptr); + if (objectref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); struct class_entry * class_entry = objectref->class_entry; - debugf("class_entry: %p\n", class_entry); struct method_entry method_entry = class_resolver_lookup_method_from_interfacemethodref_index(vm->class_hash_table.length, @@ -1204,6 +1281,8 @@ void op_irem(struct vm * vm) { int32_t value2 = operand_stack_pop_u32(vm->current_frame); int32_t value1 = operand_stack_pop_u32(vm->current_frame); + if (value2 == 0) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArithmeticException")); int32_t result = value1 % value2; operand_stack_push_u32(vm->current_frame, result); } @@ -1366,7 +1445,11 @@ void op_laload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); int64_t value = arrayref->u64[index]; operand_stack_push_u64(vm->current_frame, value); } @@ -1384,7 +1467,11 @@ void op_lastore(struct vm * vm) uint64_t value = operand_stack_pop_u64(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); arrayref->u64[index] = value; } @@ -1461,6 +1548,8 @@ void op_ldiv(struct vm * vm) { int64_t value2 = operand_stack_pop_u64(vm->current_frame); int64_t value1 = operand_stack_pop_u64(vm->current_frame); + if (value2 == 0) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArithmeticException")); int64_t result = value1 / value2; operand_stack_push_u64(vm->current_frame, result); } @@ -1546,6 +1635,8 @@ void op_lrem(struct vm * vm) { int64_t value2 = operand_stack_pop_u64(vm->current_frame); int64_t value1 = operand_stack_pop_u64(vm->current_frame); + if (value2 == 0) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArithmeticException")); int64_t result = value1 % value2; operand_stack_push_u64(vm->current_frame, result); } @@ -1699,7 +1790,10 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions) assert(dimensions > 0); int32_t dims[dimensions]; for (int i = 0; i < dimensions; i++) { - dims[dimensions - i - 1] = operand_stack_pop_u32(vm->current_frame); + int32_t dim = operand_stack_pop_u32(vm->current_frame); + if (dim < 0) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NegativeArraySizeException")); + dims[dimensions - i - 1] = dim; } struct arrayref * arrayref = _multiarray(vm, dims, dimensions, 0, type + 1, type_end); operand_stack_push_ref(vm->current_frame, arrayref); @@ -1742,6 +1836,8 @@ void op_new(struct vm * vm, uint32_t index) void op_newarray(struct vm * vm, uint32_t atype) { int32_t count = operand_stack_pop_u32(vm->current_frame); + if (count < 0) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NegativeArraySizeException")); int32_t element_size = array_element_size(atype); struct arrayref * arrayref = prim_array_allocate(vm, element_size, count); assert(arrayref != nullptr); @@ -1809,7 +1905,8 @@ void op_putfield(struct vm * vm, uint32_t index) { uint32_t value = operand_stack_pop_u32(vm->current_frame); struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); - assert(objectref != nullptr); + if (objectref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); objectref->u32[field_entry->instance_index] = value; } break; @@ -1819,7 +1916,8 @@ void op_putfield(struct vm * vm, uint32_t index) uint32_t high = operand_stack_pop_u32(vm->current_frame); uint32_t low = operand_stack_pop_u32(vm->current_frame); struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); - assert(objectref != nullptr); + if (objectref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); objectref->u32[field_entry->instance_index + 1] = high; objectref->u32[field_entry->instance_index] = low; } @@ -1896,7 +1994,11 @@ void op_saload(struct vm * vm) { int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); int16_t value = arrayref->u16[index]; operand_stack_push_u32(vm->current_frame, value); } @@ -1906,7 +2008,11 @@ void op_sastore(struct vm * vm) uint16_t value = operand_stack_pop_u32(vm->current_frame); int32_t index = operand_stack_pop_u32(vm->current_frame); struct arrayref * arrayref = operand_stack_pop_ref(vm->current_frame); - assert(arrayref->length > 0 && index >= 0 && index < arrayref->length); + if (arrayref == nullptr) + return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); + assert(arrayref->length > 0); + if (index < 0 || index >= arrayref->length) + return vm_exception(vm, vm_instance_create(vm, "java/lang/ArrayIndexOutOfBoundsException")); arrayref->u16[index] = value; } diff --git a/c/frame.c b/c/frame.c index ca64891..12fd445 100644 --- a/c/frame.c +++ b/c/frame.c @@ -392,7 +392,6 @@ void vm_exception(struct vm * vm, struct objectref * objectref) debugs("\n method: "); debug_print__method_info__method_name(vm->current_frame->class_entry->class_file, vm->current_frame->method_info); debugf("\n pc: %d", vm->current_frame->pc); - debugf("\n next_pc: %d\n", vm->current_frame->next_pc); return; } diff --git a/c/hash_table.c b/c/hash_table.c index 9037e3f..0e81c43 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -204,8 +204,6 @@ struct hash_table_entry * hash_table_add3(int hash_table_length, hash = fnv_1(hash, key3, key3_length); hash &= (hash_table_length - 1); - printf("hash: %d %u %p\n", hash_table_length, hash, value); - struct hash_table_entry * e = &entry[hash]; while (e->next != nullptr) { @@ -270,8 +268,6 @@ struct hash_table_entry * hash_table_find3(int hash_table_length, hash = fnv_1(hash, key3, key3_length); hash &= (hash_table_length - 1); - printf("hash: %d %u\n", hash_table_length, hash); - struct hash_table_entry * e = &entry[hash]; while (e != nullptr && e->key != nullptr) { diff --git a/c/native_types.h b/c/native_types.h index f402c0b..f5fefdf 100644 --- a/c/native_types.h +++ b/c/native_types.h @@ -40,6 +40,7 @@ struct arrayref { // object array: struct objectref * oref[0]; struct arrayref * aref[0]; + void * ref[0]; // primitive array: uint8_t u8[0]; uint16_t u16[0]; diff --git a/classes/java/lang/ArithmeticException.java b/classes/java/lang/ArithmeticException.java new file mode 100644 index 0000000..94fbd04 --- /dev/null +++ b/classes/java/lang/ArithmeticException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class ArithmeticException extends RuntimeException { +} diff --git a/classes/java/lang/ArrayIndexOutOfBoundsException.java b/classes/java/lang/ArrayIndexOutOfBoundsException.java new file mode 100644 index 0000000..30cb3af --- /dev/null +++ b/classes/java/lang/ArrayIndexOutOfBoundsException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException { +} diff --git a/classes/java/lang/ArrayStoreException.java b/classes/java/lang/ArrayStoreException.java new file mode 100644 index 0000000..9e9832b --- /dev/null +++ b/classes/java/lang/ArrayStoreException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class ArrayStoreException extends RuntimeException { +} diff --git a/classes/java/lang/Backtrace.java b/classes/java/lang/Backtrace.java index 609c2fe..a27fb95 100644 --- a/classes/java/lang/Backtrace.java +++ b/classes/java/lang/Backtrace.java @@ -1,3 +1,5 @@ +package java.lang; + class Backtrace { int[] backtrace_entry; // is actually (struct backtrace_entry) diff --git a/classes/java/lang/ClassCastException.java b/classes/java/lang/ClassCastException.java new file mode 100644 index 0000000..9f4bd5d --- /dev/null +++ b/classes/java/lang/ClassCastException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class ClassCastException extends RuntimeException { +} diff --git a/classes/java/lang/Error.java b/classes/java/lang/Error.java new file mode 100644 index 0000000..02f4405 --- /dev/null +++ b/classes/java/lang/Error.java @@ -0,0 +1,4 @@ +package java.lang; + +public class Error extends Throwable { +} diff --git a/classes/java/lang/IndexOutOfBoundsException.java b/classes/java/lang/IndexOutOfBoundsException.java new file mode 100644 index 0000000..6fef203 --- /dev/null +++ b/classes/java/lang/IndexOutOfBoundsException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class IndexOutOfBoundsException extends RuntimeException { +} diff --git a/classes/java/lang/NegativeArraySizeException.java b/classes/java/lang/NegativeArraySizeException.java new file mode 100644 index 0000000..ec7cea1 --- /dev/null +++ b/classes/java/lang/NegativeArraySizeException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class NegativeArraySizeException extends RuntimeException { +} diff --git a/classes/java/lang/NullPointerException.java b/classes/java/lang/NullPointerException.java new file mode 100644 index 0000000..9922a45 --- /dev/null +++ b/classes/java/lang/NullPointerException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class NullPointerException extends RuntimeException { +} diff --git a/classes/java/lang/RuntimeException.java b/classes/java/lang/RuntimeException.java new file mode 100644 index 0000000..3be7f77 --- /dev/null +++ b/classes/java/lang/RuntimeException.java @@ -0,0 +1,4 @@ +package java.lang; + +public class RuntimeException extends Exception { +} diff --git a/classes/java/lang/StringBuilder.java b/classes/java/lang/StringBuilder.java index 238f108..28f2bce 100644 --- a/classes/java/lang/StringBuilder.java +++ b/classes/java/lang/StringBuilder.java @@ -5,7 +5,7 @@ public class StringBuilder { int count; public StringBuilder() { - strings = new String[0]; + strings = new String[5]; } public StringBuilder(int capacity) { @@ -14,7 +14,9 @@ public class StringBuilder { private void ensureCapacityInternal(int minimumCapacity) { if (strings.length < minimumCapacity) { - String[] new_strings = new String[minimumCapacity + 3]; + // round up to nearest allocation unit + int new_capacity = ((minimumCapacity + 3 + 7) & (~7)) - 3; + String[] new_strings = new String[new_capacity]; for (int i = 0; i < count; i++) { new_strings[i] = strings[i]; } diff --git a/classes/test/TestRuntimeException.java b/classes/test/TestRuntimeException.java new file mode 100644 index 0000000..89ed5ed --- /dev/null +++ b/classes/test/TestRuntimeException.java @@ -0,0 +1,260 @@ +package test; + +class TestRuntimeException { + public static void testAA1() { + Object[] a = null; + Object b = a[0]; + } + + public static void testAA2() { + Object[] a = new Object[1]; + Object b = a[42]; + } + + public static void testAA3() { + Object[] a = null; + a[0] = null; + } + + public static void testAA4() { + Object[] a = new Object[1]; + a[42] = null; + } + + public static void test5() { + Object[] a = new Object[-5]; + } + + public static void test6() { + Object[] a = null; + int b = a.length; + } + + public static void test7() throws Exception { + Exception e = null; + throw e; + } + + public static void testBA1() { + byte[] a = null; + byte b = a[0]; + } + + public static void testBA2() { + byte[] a = new byte[1]; + byte b = a[42]; + } + + public static void testBA3() { + byte[] a = null; + a[0] = 0; + } + + public static void testBA4() { + byte[] a = new byte[1]; + a[42] = 0; + } + + public static void testCA1() { + char[] a = null; + char b = a[0]; + } + + public static void testCA2() { + char[] a = new char[1]; + char b = a[42]; + } + + public static void testCA3() { + char[] a = null; + a[0] = 0; + } + + public static void testCA4() { + char[] a = new char[1]; + a[42] = 0; + } + + public static void testCC() { + NullPointerException a = new NullPointerException(); + Object b = a; + ArrayIndexOutOfBoundsException c = (ArrayIndexOutOfBoundsException)b; + } + + public static void testDA1() { + double[] a = null; + double b = a[0]; + } + + public static void testDA2() { + double[] a = new double[1]; + double b = a[42]; + } + + public static void testDA3() { + double[] a = null; + a[0] = 0; + } + + public static void testDA4() { + double[] a = new double[1]; + a[42] = 0; + } + + public static void testFA1() { + float[] a = null; + float b = a[0]; + } + + public static void testFA2() { + float[] a = new float[1]; + float b = a[42]; + } + + public static void testFA3() { + float[] a = null; + a[0] = 0; + } + + public static void testFA4() { + float[] a = new float[1]; + a[42] = 0; + } + + public static void testIA1() { + int[] a = null; + int b = a[0]; + } + + public static void testIA2() { + int[] a = new int[1]; + int b = a[42]; + } + + public static void testIA3() { + int[] a = null; + a[0] = 0; + } + + public static void testIA4() { + int[] a = new int[1]; + a[42] = 0; + } + + public static void testidiv() { + int a = 42; + int b = 0; + int c = a / b; + } + + public static void testirem() { + int a = 42; + int b = 0; + int c = a % b; + } + + public static void testldiv() { + long a = 42; + long b = 0; + long c = a / b; + } + + public static void testlrem() { + long a = 42; + long b = 0; + long c = a % b; + } + + public static void testLA1() { + long[] a = null; + long b = a[0]; + } + + public static void testLA2() { + long[] a = new long[1]; + long b = a[42]; + } + + public static void testLA3() { + long[] a = null; + a[0] = 0; + } + + public static void testLA4() { + long[] a = new long[1]; + a[42] = 0; + } + + public static void testmultianewarray() { + int[][] a = new int[-1][-1]; + } + + public static void testnewarray() { + int[] a = new int[-1]; + } + + public static void testSA1() { + short[] a = null; + short b = a[0]; + } + + public static void testSA2() { + short[] a = new short[1]; + short b = a[42]; + } + + public static void testSA3() { + short[] a = null; + a[0] = 0; + } + + public static void testSA4() { + short[] a = new short[1]; + a[42] = 0; + } + + public static void main() throws Exception { + //testAA1(); + //testAA2(); + //testAA3(); + //testAA4(); + //test5(); + //test6(); + //test7(); + //testBA1(); + //testBA2(); + //testBA3(); + //testBA4(); + //testCA1(); + //testCA2(); + //testCA3(); + //testCA4(); + //testCC(); + //testDA1(); + //testDA2(); + //testDA3(); + //testDA4(); + //testFA1(); + //testFA2(); + //testFA3(); + //testFA4(); + //testIA1(); + //testIA2(); + //testIA3(); + //testIA4(); + //testidiv(); + //testirem(); + //testldiv(); + //testlrem(); + //testLA1(); + //testLA2(); + //testLA3(); + //testLA4(); + //testmultianewarray(); + //testnewarray(); + //testSA1(); + //testSA2(); + //testSA3(); + //testSA4(); + } +}