Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 include/runtime/classloader.h |    1 +
 include/vm/class.h            |    1 +
 include/vm/classloader.h      |    1 +
 include/vm/preload.h          |    1 +
 runtime/classloader.c         |   40 +++++++++++++++++++++++++++++++++++++++-
 test/vm/preload-stub.c        |    1 +
 vm/class.c                    |   35 ++++++++++++++++++++++++++++++++++-
 vm/classloader.c              |   28 ++++++++++++++++++++++++++++
 vm/jato.c                     |    1 +
 vm/preload.c                  |    2 ++
 10 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/include/runtime/classloader.h b/include/runtime/classloader.h
index 2f034ae..7cc602b 100644
--- a/include/runtime/classloader.h
+++ b/include/runtime/classloader.h
@@ -6,5 +6,6 @@
 jobject native_vmclassloader_getprimitiveclass(jint type);
 jobject native_vmclassloader_findloadedclass(jobject classloader, jobject 
name);
 jobject native_vmclassloader_loadclass(jobject name, jboolean resolve);
+jobject native_vmclassloader_defineclass(jobject classloader, jobject name, 
jobject data, jint offset, jint len, jobject pd);
 
 #endif /* RUNTIME_CLASSLOADER_H */
diff --git a/include/vm/class.h b/include/vm/class.h
index 4451680..bdb17b3 100644
--- a/include/vm/class.h
+++ b/include/vm/class.h
@@ -185,6 +185,7 @@ struct vm_class *vm_class_get_array_element_class(const 
struct vm_class *array_c
 enum vm_type vm_class_get_storage_vmtype(const struct vm_class *class);
 struct vm_class *vm_class_get_class_from_class_object(struct vm_object *clazz);
 struct vm_class *vm_class_get_array_class(struct vm_class *element_class);
+struct vm_class *vm_class_define(const char *name, uint8_t *data, unsigned 
long len);
 
 #define DECLARE_STATIC_FIELD_GETTER(type)                              \
 static inline j ## type                                                        
\
diff --git a/include/vm/classloader.h b/include/vm/classloader.h
index 12873b4..3c5409c 100644
--- a/include/vm/classloader.h
+++ b/include/vm/classloader.h
@@ -17,5 +17,6 @@ struct vm_class *classloader_load(struct vm_object *loader,
                                  const char *class_name);
 struct vm_class *classloader_load_primitive(const char *class_name);
 struct vm_class *classloader_find_class(struct vm_object *loader, const char 
*name);
+int classloader_add_to_cache(struct vm_object *loader, struct vm_class *class);
 
 #endif
diff --git a/include/vm/preload.h b/include/vm/preload.h
index d09f6b7..cd060d3 100644
--- a/include/vm/preload.h
+++ b/include/vm/preload.h
@@ -50,6 +50,7 @@ extern struct vm_class *vm_java_lang_IllegalArgumentException;
 extern struct vm_class *vm_java_lang_ClassLoader;
 extern struct vm_class *vm_java_lang_Number;
 extern struct vm_class *vm_java_lang_InterruptedException;
+extern struct vm_class *vm_java_lang_ClassFormatError;
 extern struct vm_class *vm_boolean_class;
 extern struct vm_class *vm_char_class;
 extern struct vm_class *vm_float_class;
diff --git a/runtime/classloader.c b/runtime/classloader.c
index 9258c40..029f562 100644
--- a/runtime/classloader.c
+++ b/runtime/classloader.c
@@ -29,8 +29,9 @@
 #include "runtime/classloader.h"
 
 #include "vm/class.h"
-#include "vm/object.h"
 #include "vm/classloader.h"
+#include "vm/object.h"
+#include "vm/preload.h"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -92,3 +93,40 @@ jobject native_vmclassloader_loadclass(jobject name, 
jboolean resolve)
 
        return vmc->object;
 }
+
+jobject native_vmclassloader_defineclass(jobject classloader, jobject name,
+       jobject data, jint offset, jint len, jobject pd)
+{
+       struct vm_class *class;
+       char *c_name;
+       uint8_t *buf;
+
+       buf = malloc(len);
+       if (!buf) {
+               signal_new_exception(vm_java_lang_OutOfMemoryError, NULL);
+               return NULL;
+       }
+
+       for (jint i = 0; i < len; i++)
+               buf[i] = array_get_field_byte(data, offset + i);
+
+       if (name)
+               c_name = vm_string_to_cstr(name);
+       else
+               c_name = strdup("unknown");
+
+       class = vm_class_define(c_name, buf, len);
+       free(buf);
+
+       if (!class)
+               return NULL;
+
+       class->classloader = classloader;
+       if (classloader_add_to_cache(classloader, class)) {
+               signal_new_exception(vm_java_lang_OutOfMemoryError, NULL);
+               return NULL;
+       }
+
+       vm_class_ensure_object(class);
+       return class->object;
+}
diff --git a/test/vm/preload-stub.c b/test/vm/preload-stub.c
index ca3e77f..aec88ec 100644
--- a/test/vm/preload-stub.c
+++ b/test/vm/preload-stub.c
@@ -54,6 +54,7 @@ struct vm_class *vm_java_lang_VMThread;
 struct vm_class *vm_java_lang_IllegalMonitorStateException;
 struct vm_class *vm_java_lang_OutOfMemoryError;
 struct vm_class *vm_java_lang_InterruptedException;
+struct vm_class *vm_java_lang_ClassFormatError;
 
 struct vm_method *vm_java_lang_Throwable_initCause;
 struct vm_method *vm_java_lang_Throwable_getCause;
diff --git a/vm/class.c b/vm/class.c
index 6edf2e4..9d3c9ec 100644
--- a/vm/class.c
+++ b/vm/class.c
@@ -733,7 +733,7 @@ struct vm_class *vm_class_resolve_class(const struct 
vm_class *vmc, uint16_t i)
        struct vm_class *class
                = classloader_load(vmc->classloader, class_name_str);
        if (!class) {
-               NOT_IMPLEMENTED;
+               warn("failed to load class %s", class_name_str);
                return NULL;
        }
 
@@ -1171,3 +1171,36 @@ struct vm_class *vm_class_get_array_class(struct 
vm_class *element_class)
        free(name);
        return result;
 }
+
+struct vm_class *
+vm_class_define(const char *name, uint8_t *data, unsigned long len)
+{
+       struct cafebabe_stream stream;
+       struct cafebabe_class *class;
+       struct vm_class *result = NULL;
+
+       cafebabe_stream_open_buffer(&stream, data, len);
+
+       class = malloc(sizeof *class);
+       if (cafebabe_class_init(class, &stream)) {
+               signal_new_exception(vm_java_lang_ClassFormatError, NULL);
+               goto out_stream;
+       }
+
+       cafebabe_stream_close_buffer(&stream);
+
+       result = malloc(sizeof *result);
+       if (!result) {
+               signal_new_exception(vm_java_lang_OutOfMemoryError, NULL);
+               return NULL;
+       }
+
+       if (vm_class_link(result, class))
+               return NULL;
+
+       return result;
+
+out_stream:
+       cafebabe_stream_close_buffer(&stream);
+       return NULL;
+}
diff --git a/vm/classloader.c b/vm/classloader.c
index ce173b5..c31ae24 100644
--- a/vm/classloader.c
+++ b/vm/classloader.c
@@ -721,3 +721,31 @@ classloader_find_class(struct vm_object *loader, const 
char *name)
        pthread_mutex_unlock(&classloader_mutex);
        return vmc;
 }
+
+int classloader_add_to_cache(struct vm_object *loader, struct vm_class *vmc)
+{
+       struct classloader_class *class;
+
+       class = malloc(sizeof(*class));
+       if (!class)
+               return -ENOMEM;
+
+       class->class = vmc;
+       class->status = CLASS_LOADED;
+       class->nr_waiting = 0;
+       class->loading_thread = vm_thread_self();
+       class->key.classloader = loader;
+       class->key.class_name = strdup(vmc->name);
+
+       pthread_mutex_lock(&classloader_mutex);
+
+       if (hash_map_put(classes, &class->key, class)) {
+               pthread_mutex_unlock(&classloader_mutex);
+               free(class->key.class_name);
+               free(class);
+               return -ENOMEM;
+       }
+
+       pthread_mutex_unlock(&classloader_mutex);
+       return 0;
+}
diff --git a/vm/jato.c b/vm/jato.c
index 8980d73..27a5be1 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -536,6 +536,7 @@ static struct vm_native natives[] = {
        DEFINE_NATIVE("java/lang/VMClass", "isInstance", 
native_vmclass_isinstance),
        DEFINE_NATIVE("java/lang/VMClass", "isInterface", 
native_vmclass_isinterface),
        DEFINE_NATIVE("java/lang/VMClass", "isPrimitive", 
native_vmclass_isprimitive),
+       DEFINE_NATIVE("java/lang/VMClassLoader", "defineClass", 
native_vmclassloader_defineclass),
        DEFINE_NATIVE("java/lang/VMClassLoader", "findLoadedClass", 
native_vmclassloader_findloadedclass),
        DEFINE_NATIVE("java/lang/VMClassLoader", "getPrimitiveClass", 
native_vmclassloader_getprimitiveclass),
        DEFINE_NATIVE("java/lang/VMClassLoader", "loadClass", 
native_vmclassloader_loadclass),
diff --git a/vm/preload.c b/vm/preload.c
index ba2d50f..d60da48 100644
--- a/vm/preload.c
+++ b/vm/preload.c
@@ -91,6 +91,7 @@ struct vm_class *vm_java_lang_Short;
 struct vm_class *vm_java_lang_VMString;
 struct vm_class *vm_java_lang_Number;
 struct vm_class *vm_java_lang_InterruptedException;
+struct vm_class *vm_java_lang_ClassFormatError;
 struct vm_class *vm_boolean_class;
 struct vm_class *vm_char_class;
 struct vm_class *vm_float_class;
@@ -142,6 +143,7 @@ static const struct preload_entry preload_entries[] = {
        { "[java/lang/reflect/Method", &vm_array_of_java_lang_reflect_Method },
        { "java/lang/IllegalArgumentException", 
&vm_java_lang_IllegalArgumentException },
        { "java/lang/InterruptedException", &vm_java_lang_InterruptedException 
},
+       { "java/lang/ClassFormatError", &vm_java_lang_ClassFormatError },
        { "java/lang/Boolean", &vm_java_lang_Boolean },
        { "java/lang/Byte", &vm_java_lang_Byte },
        { "java/lang/Character", &vm_java_lang_Character },
-- 
1.6.0.4


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to