implement java.lang.Class.getName

This commit is contained in:
Zack Buhman 2025-01-10 21:58:43 -06:00
parent aaa55a4f9d
commit 008690543d
10 changed files with 130 additions and 22 deletions

View File

@ -441,13 +441,21 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
struct attribute_info * attribute = find_attribute(code_index, struct attribute_info * attribute = find_attribute(code_index,
method_info->attributes_count, method_info->attributes_count,
method_info->attributes); method_info->attributes);
assert(attribute != nullptr);
return (struct method_entry){ if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) {
.class_entry = class_entry, return (struct method_entry){
.method_info = method_info, .class_entry = class_entry,
.code_attribute = attribute->code, .method_info = method_info,
}; .code_attribute = nullptr,
};
} else {
assert(attribute != nullptr);
return (struct method_entry){
.class_entry = class_entry,
.method_info = method_info,
.code_attribute = attribute->code,
};
}
} }
if (class_entry->class_file->super_class == 0) if (class_entry->class_file->super_class == 0)
@ -606,24 +614,12 @@ struct objectref * class_resolver_lookup_string(struct vm * vm,
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1]; struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1];
assert(utf8_constant->tag == CONSTANT_Utf8); assert(utf8_constant->tag == CONSTANT_Utf8);
int32_t count = utf8_constant->utf8.length; struct objectref * string_objectref = vm_instance_string_from_constant(vm, utf8_constant);
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
assert(arrayref != nullptr);
arrayref->class_entry = nullptr; // byte[]
arrayref->length = utf8_constant->utf8.length;
for (int i = 0; i < utf8_constant->utf8.length; i++) {
arrayref->u8[i] = utf8_constant->utf8.bytes[i];
}
struct objectref * objectref = vm_instance_create(vm, "java/lang/String");
assert(objectref != nullptr);
assert(objectref->class_entry->instance_fields_count >= 1);
objectref->aref[0] = arrayref;
// cache the result // cache the result
class_entry->attribute_entry[string_index - 1].string_objectref = objectref; class_entry->attribute_entry[string_index - 1].string_objectref = string_objectref;
return objectref; return string_objectref;
} }
bool class_resolver_instanceof(int class_hash_table_length, bool class_resolver_instanceof(int class_hash_table_length,

View File

@ -3,10 +3,12 @@
#include "string.h" #include "string.h"
#include "printf.h" #include "printf.h"
#include "native.h" #include "native.h"
#include "native/class.h"
#include "native/loader.h"
#include "native/math.h" #include "native/math.h"
#include "native/memory.h" #include "native/memory.h"
#include "native/object.h"
#include "native/printstream.h" #include "native/printstream.h"
#include "native/loader.h"
typedef void (* native_func_t)(struct vm * vm, uint32_t * args); typedef void (* native_func_t)(struct vm * vm, uint32_t * args);
@ -102,6 +104,24 @@ const static struct native_method native_method[] = {
.method_descriptor = "()I", .method_descriptor = "()I",
.func = native_jvm_internal_loader_getbuffer_0, .func = native_jvm_internal_loader_getbuffer_0,
}, },
{
.class_name = "java/lang/Class",
.method_name = "getClassName",
.method_descriptor = "()Ljava/lang/String;",
.func = native_java_lang_class_getclassname_1,
},
{
.class_name = "java/lang/Object",
.method_name = "getClass",
.method_descriptor = "()Ljava/lang/Class;",
.func = native_java_lang_object_getclass_1,
},
{
.class_name = "java/lang/Object",
.method_name = "hashCode",
.method_descriptor = "()I",
.func = native_java_lang_object_hashcode_1,
},
}; };
struct hash_table_entry * native_init_hash_table(int * hash_table_length) struct hash_table_entry * native_init_hash_table(int * hash_table_length)

23
c/native/class.c Normal file
View File

@ -0,0 +1,23 @@
#include "class.h"
#include "printf.h"
#include "vm_instance.h"
void native_java_lang_class_getclassname_1(struct vm * vm, uint32_t * args)
{
struct objectref * objectref = (struct objectref *)args[0];
assert(objectref != nullptr);
assert(objectref->oref[0] != nullptr);
assert(objectref->oref[0]->class_entry != nullptr);
struct class_file * class_file = objectref->oref[0]->class_entry->class_file;
struct constant * class_constant = &class_file->constant_pool[class_file->this_class - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
struct objectref * string_objectref = vm_instance_string_from_constant(vm, class_name_constant);
operand_stack_push_ref(vm->current_frame, string_objectref);
}

7
c/native/class.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
#include "frame.h"
void native_java_lang_class_getclassname_1(struct vm * vm, uint32_t * args);

23
c/native/object.c Normal file
View File

@ -0,0 +1,23 @@
#include "object.h"
#include "printf.h"
#include "vm_instance.h"
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args)
{
struct objectref * objectref = (struct objectref *)args[0];
assert(objectref != nullptr);
struct objectref * class_objectref = vm_instance_create(vm, "java/lang/Class");
assert(class_objectref != nullptr);
assert(class_objectref->class_entry->instance_fields_count >= 1);
class_objectref->oref[0] = objectref;
operand_stack_push_ref(vm->current_frame, class_objectref);
}
void native_java_lang_object_hashcode_1(struct vm * vm, uint32_t * args)
{
struct objectref * objectref = (struct objectref *)args[0];
operand_stack_push_u32(vm->current_frame, (uint32_t)objectref); // objectref as integer
}

9
c/native/object.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
#include "frame.h"
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args);
void native_java_lang_object_hashcode_1(struct vm * vm, uint32_t * args);

View File

@ -21,3 +21,22 @@ struct objectref * vm_instance_create(struct vm * vm, const char * class_name)
return objectref; return objectref;
} }
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant)
{
int32_t count = constant->utf8.length;
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
assert(arrayref != nullptr);
arrayref->class_entry = nullptr; // byte[]
arrayref->length = constant->utf8.length;
for (int i = 0; i < constant->utf8.length; i++) {
arrayref->u8[i] = constant->utf8.bytes[i];
}
struct objectref * objectref = vm_instance_create(vm, "java/lang/String");
assert(objectref != nullptr);
assert(objectref->class_entry->instance_fields_count >= 1);
objectref->aref[0] = arrayref;
return objectref;
}

View File

@ -3,3 +3,4 @@
#include "frame.h" #include "frame.h"
struct objectref * vm_instance_create(struct vm * vm, const char * class_name); struct objectref * vm_instance_create(struct vm * vm, const char * class_name);
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant);

View File

@ -0,0 +1,8 @@
package test;
class TestClass {
public static void main() {
TestClass obj = new TestClass();
System.out.println(obj.getClass().getName());
}
}

View File

@ -21,9 +21,11 @@ OBJ = \
c/malloc.o \ c/malloc.o \
c/memory_allocator.o \ c/memory_allocator.o \
c/native.o \ c/native.o \
c/native/class.o \
c/native/loader.o \ c/native/loader.o \
c/native/math.o \ c/native/math.o \
c/native/memory.o \ c/native/memory.o \
c/native/object.o \
c/native/printstream.o \ c/native/printstream.o \
c/parse.o \ c/parse.o \
c/parse_type.o \ c/parse_type.o \