-/* native/vm/VMClassLoader.c - java/lang/VMClassLoader
+/* src/native/vm/VMClassLoader.c - java/lang/VMClassLoader
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+ Contact: cacao@cacaojvm.org
Authors: Roman Obermaiser
Changes: Joseph Wenninger
Christian Thalinger
+ Edwin Steiner
- $Id: VMClassLoader.c 2201 2005-04-03 21:48:11Z twisti $
+ $Id: VMClassLoader.c 4357 2006-01-22 23:33:38Z twisti $
*/
#include <sys/stat.h>
#include "config.h"
-#include "types.h"
+#include "vm/types.h"
+
#include "mm/memory.h"
#include "native/jni.h"
#include "native/native.h"
#include "native/include/java_security_ProtectionDomain.h"
#include "native/include/java_util_Vector.h"
#include "toolbox/logging.h"
+#include "vm/builtin.h"
#include "vm/class.h"
#include "vm/classcache.h"
#include "vm/exceptions.h"
-#include "vm/builtin.h"
+#include "vm/initialize.h"
+#include "vm/linker.h"
#include "vm/loader.h"
#include "vm/options.h"
#include "vm/statistics.h"
#include "vm/stringlocal.h"
-#include "vm/tables.h"
+#include "vm/suck.h"
+#include "vm/zip.h"
#include "vm/jit/asmpart.h"
* Method: defineClass
* Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
*/
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *this, java_lang_String *name, java_bytearray *buf, s4 off, s4 len, java_security_ProtectionDomain *pd)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_bytearray *data, s4 offset, s4 len, java_security_ProtectionDomain *pd)
{
classinfo *c;
classinfo *r;
classbuffer *cb;
utf *utfname;
- if ((off < 0) || (len < 0) || ((off + len) > buf->header.size)) {
- *exceptionptr =
- new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
- return NULL;
- }
+ /* check if data was passed */
- /* thrown by SUN jdk */
- if (len == 0) {
- *exceptionptr = new_classformaterror(NULL, "Truncated class file");
+ if (data == NULL) {
+ exceptions_throw_nullpointerexception();
return NULL;
}
- if (!name) {
- /* XXX we have to support this case (name is read from classbuffer) */
- log_text("defineClass(name == NULL,...) is not implemented, yet");
- *exceptionptr = new_nullpointerexception();
+ /* check the indexes passed */
+
+ if ((offset < 0) || (len < 0) || ((offset + len) > data->header.size)) {
+ exceptions_throw_arrayindexoutofboundsexception();
return NULL;
}
- /* convert '.' to '/' in java string */
- utfname = javastring_toutf(name, true);
-
- /* check if this class has already been defined */
- c = classcache_lookup_defined((java_objectheader *) this, utfname);
- if (c)
- return (java_lang_Class *) c;
+ if (name) {
+ /* convert '.' to '/' in java string */
+
+ utfname = javastring_toutf(name, true);
+
+ /* check if this class has already been defined */
+
+ c = classcache_lookup_defined_or_initiated((java_objectheader *) cl, utfname);
+ if (c) {
+ *exceptionptr =
+ exceptions_new_linkageerror("duplicate class definition: ",c);
+ return NULL;
+ }
+ }
+ else {
+ utfname = NULL;
+ }
/* create a new classinfo struct */
- c = class_create_classinfo(utfname);
-#if defined(USE_THREADS)
- /* enter a monitor on the class */
- builtin_monitorenter((java_objectheader *) c);
-#endif
+ c = class_create_classinfo(utfname);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
/* measure time */
if (getloadingtime)
cb = NEW(classbuffer);
cb->class = c;
- cb->size = len;
- cb->data = (u1 *) &buf->data[off];
- cb->pos = cb->data - 1;
+ cb->size = len;
+ cb->data = (u1 *) &data->data[offset];
+ cb->pos = cb->data;
/* preset the defining classloader */
- c->classloader = (java_objectheader *) this;
+ c->classloader = (java_objectheader *) cl;
/* load the class from this buffer */
FREE(cb, classbuffer);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
/* measure time */
if (getloadingtime)
loadingtime_stop();
#endif
-#if defined(USE_THREADS)
- /* leave the monitor */
-
- builtin_monitorexit((java_objectheader *) c);
-#endif
-
- /* exception? return! */
-
if (!r) {
- /* If return value is NULL, we had a problem and the class is not */
+ /* If return value is NULL, we had a problem and the class is not */
/* loaded. */
- /* now free the allocated memory, otherwise we could ran into a DOS */
+ /* now free the allocated memory, otherwise we could run into a DOS */
class_free(c);
/* set ProtectionDomain */
- c->pd = pd;
+ c->object.pd = pd;
+
+ /* Store the newly defined class in the class cache. This call also */
+ /* checks whether a class of the same name has already been defined by */
+ /* the same defining loader, and if so, replaces the newly created class */
+ /* by the one defined earlier. */
+ /* Important: The classinfo given to classcache_store_defined must be */
+ /* fully prepared because another thread may return this */
+ /* pointer after the lookup at to top of this function */
+ /* directly after the class cache lock has been released. */
- use_class_as_object(c);
+ c = classcache_store_defined(c);
return (java_lang_Class *) c;
}
/*
* Class: java/lang/VMClassLoader
* Method: getPrimitiveClass
- * Signature: (Ljava/lang/String;)Ljava/lang/Class;
+ * Signature: (C)Ljava/lang/Class;
*/
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, java_lang_String *type)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, s4 type)
{
classinfo *c;
- utf *u;
-
- u = javastring_toutf(type, false);
- /* illegal primitive classname specified */
+ /* get primitive class */
- if (!u) {
+ switch (type) {
+ case 'I':
+ c = primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
+ break;
+ case 'J':
+ c = primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
+ break;
+ case 'F':
+ c = primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
+ break;
+ case 'D':
+ c = primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
+ break;
+ case 'B':
+ c = primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
+ break;
+ case 'C':
+ c = primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
+ break;
+ case 'S':
+ c = primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
+ break;
+ case 'Z':
+ c = primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
+ break;
+ case 'V':
+ c = primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
+ break;
+ default:
*exceptionptr = new_exception(string_java_lang_ClassNotFoundException);
- return NULL;
+ c = NULL;
}
- /* get primitive class */
-
- if (!load_class_bootstrap(u, &c) || !initialize_class(c))
- return NULL;
-
- use_class_as_object(c);
-
return (java_lang_Class *) c;
}
ci = (classinfo *) c;
if (!ci) {
- *exceptionptr = new_nullpointerexception();
+ exceptions_throw_nullpointerexception();
return;
}
/* link the class */
- if (!ci->linked)
- link_class(ci);
+ if (!(ci->state & CLASS_LINKED))
+ (void) link_class(ci);
return;
}
utf *u;
if (!name) {
- *exceptionptr = new_nullpointerexception();
+ exceptions_throw_nullpointerexception();
return NULL;
}
/* load class */
- if (!load_class_bootstrap(u,&c))
+ if (!(c = load_class_bootstrap(u)))
goto exception;
/* resolve class -- if requested */
/* if (resolve) { */
if (!link_class(c))
goto exception;
-
- use_class_as_object(c);
/* } */
return (java_lang_Class *) c;
*/
JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, java_lang_String *name)
{
- jobject o;
- methodinfo *m;
- java_lang_String *path;
- classpath_info *cpi;
- utf *utfname;
- char *charname;
- char *tmppath;
- s4 namelen;
- s4 pathlen;
- struct stat buf;
- jboolean ret;
+ jobject o;
+ methodinfo *m;
+ java_lang_String *path;
+ list_classpath_entry *lce;
+ utf *utfname;
+ char *charname;
+ char *end;
+ char *tmppath;
+ s4 namelen;
+ s4 pathlen;
+ struct stat buf;
+ jboolean ret;
/* get the resource name as utf string */
utf_sprint(charname, utfname);
+ /* search for `.class', if found remove it */
+
+ if ((end = strstr(charname, ".class"))) {
+ *end = '\0';
+ utfname = utf_new_char(charname);
+
+ /* little hack, but it should work */
+ *end = '.';
+ }
+
/* new Vector() */
o = native_new_and_init(class_java_util_Vector);
if (!o)
return NULL;
- /* get v.add() method */
+ /* get Vector.add() method */
m = class_resolveclassmethod(class_java_util_Vector,
- utf_new_char("add"),
+ utf_add,
utf_new_char("(Ljava/lang/Object;)Z"),
NULL,
true);
if (!m)
return NULL;
- for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
+ for (lce = list_first(list_classpath_entries); lce != NULL;
+ lce = list_next(list_classpath_entries, lce)) {
/* clear path pointer */
path = NULL;
-#if defined(USE_ZLIB)
- if (cpi->type == CLASSPATH_ARCHIVE) {
-
-#if defined(USE_THREADS)
- /* enter a monitor on zip/jar archives */
-
- builtin_monitorenter((java_objectheader *) cpi);
-#endif
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
- if (cacao_locate(cpi->uf, utfname) == UNZ_OK) {
- pathlen = strlen("jar:file://") + cpi->pathlen + strlen("!/") +
+ if (zip_find(lce, utfname)) {
+ pathlen = strlen("jar:file://") + lce->pathlen + strlen("!/") +
namelen + strlen("0");
tmppath = MNEW(char, pathlen);
- sprintf(tmppath, "jar:file://%s!/%s", cpi->path, charname);
+ sprintf(tmppath, "jar:file://%s!/%s", lce->path, charname);
path = javastring_new_char(tmppath),
MFREE(tmppath, char, pathlen);
}
-#if defined(USE_THREADS)
- /* leave the monitor */
-
- builtin_monitorexit((java_objectheader *) cpi);
-#endif
-
} else {
-#endif /* defined(USE_ZLIB) */
- pathlen = strlen("file://") + cpi->pathlen + namelen + strlen("0");
+#endif /* defined(ENABLE_ZLIB) */
+ pathlen = strlen("file://") + lce->pathlen + namelen + strlen("0");
tmppath = MNEW(char, pathlen);
- sprintf(tmppath, "file://%s%s", cpi->path, charname);
+ sprintf(tmppath, "file://%s%s", lce->path, charname);
if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
path = javastring_new_char(tmppath),
MFREE(tmppath, char, pathlen);
-#if defined(USE_ZLIB)
+#if defined(ENABLE_ZLIB)
}
#endif
/* if a resource was found, add it to the vector */
if (path) {
- ret = (jboolean) asm_calljavafunction_int(m, o, path, NULL, NULL);
+ ASM_CALLJAVAFUNCTION_INT(ret, m, o, path, NULL, NULL);
if (!ret)
return NULL;
}
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: findLoadedClass
+ * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
+ */
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name)
+{
+ classinfo *c;
+ utf *u;
+
+ /* replace `.' by `/', this is required by the classcache */
+
+ u = javastring_toutf(name, true);
+
+ /* lookup for defining classloader */
+
+ c = classcache_lookup_defined((classloader *) cl, u);
+
+ /* if not found, lookup for initiating classloader */
+
+ if (c == NULL)
+ c = classcache_lookup((classloader *) cl, u);
+
+ return (java_lang_Class *) c;
+}
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where