Index: vm/vmcore/include/classloader.h =================================================================== --- vm/vmcore/include/classloader.h (revision 509500) +++ vm/vmcore/include/classloader.h (working copy) @@ -170,6 +170,8 @@ Class* LookupClass(const String* name) { LMAutoUnlock aulock(&m_lock); Class** klass = m_loadedClasses->Lookup(name); + if(klass == NULL) + klass = m_initiatedClasses->Lookup(name); return klass?*klass:NULL; } void InsertClass(Class* clss) { Index: vm/vmcore/include/vm_threads.h =================================================================== --- vm/vmcore/include/vm_threads.h (revision 509500) +++ vm/vmcore/include/vm_threads.h (working copy) @@ -86,6 +86,11 @@ */ ClassLoader* onload_caller; + /** + * Flag shows which class is loaded original or subordinated. + */ + bool is_original; + // In case exception is thrown, Exception object is put here // TODO: Needs to be replaced with jobject! //volatile ManagedObject* p_exception_object; Index: vm/vmcore/src/jni/jni.cpp =================================================================== --- vm/vmcore/src/jni/jni.cpp (revision 509500) +++ vm/vmcore/src/jni/jni.cpp (working copy) @@ -565,54 +565,6 @@ ClassLoader* cl; if (loader != NULL) { - if(name) - { - jclass clazz = GetObjectClass(jenv, loader); - jmethodID meth_id = GetMethodID(jenv, clazz, "findLoadedClass", "(Ljava/lang/String;)Ljava/lang/Class;"); - if (NULL == meth_id) - { - jobject exn = exn_get(); - tmn_suspend_disable(); - Class *exn_class = exn->object->vt()->clss; - assert(exn_class); - bool f = exn_class != env->java_lang_OutOfMemoryError_Class; - tmn_suspend_enable(); - if(f) - LDIE(19, "Fatal: an access to findLoadedClass method of java.lang.Class is not provided"); - // OutOfMemoryError should be rethrown after this JNI method exits - return 0; - } - jstring str = NewStringUTF(jenv, name); - if (NULL == str) - { - // the only OutOfMemoryError can be a reason to be here; it will be rethrown after this JNI method exits - return 0; - } - jobject obj = CallObjectMethod(jenv, loader, meth_id, str); - if(obj) - { - jthrowable exn; - if(exn_raised()) - { - // pending exception will be rethrown after the JNI method exits - return 0; - } - else - { - static const char* mess_templ = "duplicate class definition: "; - static unsigned mess_templ_len = strlen(mess_templ); - unsigned mess_size = mess_templ_len + strlen(name) + 1; // 1 is for trailing '\0' - char* err_mess = (char*)STD_ALLOCA(mess_size); - sprintf(err_mess, "%s%s", mess_templ, name); - exn = exn_create("java/lang/LinkageError", err_mess); - } - - assert(exn); - jint UNUSED ok = Throw(jenv, exn); - assert(ok == 0); - return 0; - } - } cl = class_loader_lookup(loader); } else Index: vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp =================================================================== --- vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp (revision 509500) +++ vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp (working copy) @@ -38,6 +38,7 @@ #include "vm_strings.h" #include "java_lang_VMClassRegistry.h" +#include "java_lang_ClassLoader.h" /* * Class: java_lang_VMClassRegistry @@ -85,86 +86,45 @@ return clss; } +JNIEXPORT jclass JNICALL Java_java_lang_VMClassRegistry_loadBootstrapClass + (JNIEnv *jenv, jclass, jstring name) +{ + // obtain char* for the name + const char* buf = GetStringUTFChars(jenv, name, NULL); + // set flag to determine that class is original + p_TLS_vmthread->is_original = true; + Class_Handle clss = class_find_class_from_loader(NULL, buf, FALSE); + ReleaseStringUTFChars(jenv, name, buf); + if (clss) { + // filter out primitive types for compatibility + return clss->is_primitive() ? NULL : jni_class_from_handle(jenv, clss); + } else { + assert(exn_raised()); + if(p_TLS_vmthread->is_original) { + exn_clear(); + } + return NULL; + } +} + /* * Class: java_lang_VMClassRegistry * Method: findLoadedClass * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/Class; */ -JNIEXPORT jclass JNICALL Java_java_lang_VMClassRegistry_findLoadedClass - (JNIEnv *jenv, jclass, jstring name, jobject cl) +JNIEXPORT jclass JNICALL Java_java_lang_ClassLoader_findLoadedClass + (JNIEnv *jenv, jobject cl, jstring name) { - ASSERT_RAISE_AREA; - - // check the name is provided - if (name == NULL) { - ThrowNew_Quick(jenv, "java/lang/NullPointerException", "null class name value."); - return NULL; - } - - // obtain char* for the name - unsigned length = GetStringUTFLength(jenv, name); - char* buf = (char*)STD_MALLOC(length+1); - assert(buf); - GetStringUTFRegion(jenv, name, 0, GetStringLength(jenv, name), buf); - - // check for wrong symbols - if (strcspn(buf, "/[;") < length) { - STD_FREE(buf); - return NULL; - } - - // filter out primitive types - - Global_Env *ge = jni_get_vm_env(jenv); - Class* primitives[] = { - ge->Boolean_Class, - ge->Char_Class, - ge->Float_Class, - ge->Double_Class, - ge->Byte_Class, - ge->Short_Class, - ge->Int_Class, - ge->Long_Class, - ge->Void_Class, - }; - int primitives_len = sizeof(primitives) / sizeof(Class*); - - for (int i = 0; i < primitives_len; i++) { - if (primitives[i] && primitives[i]->get_name()) { - char *pname = (char*)primitives[i]->get_name()->bytes; - if (0 == strcmp(buf, pname)) { - STD_FREE(buf); - return NULL; - } - } - } - - ClassLoaderHandle loader = NULL; - Class_Handle clss = NULL; - jclass jclss = NULL; - - if(cl) { - // if non null class loader is provided, search among loaded classes - loader = class_loader_lookup(cl); - clss = class_find_loaded(loader, buf); - } else { - // if null class loader is specified - // load class using bootstrap class loader - // clss = class_find_class_from_loader(NULL, buf, TRUE); - clss = class_find_class_from_loader(NULL, buf, FALSE); - } - - STD_FREE(buf); - - if (clss) - jclss = jni_class_from_handle(jenv, clss); - - if (ExceptionOccurred(jenv)) { - ExceptionClear(jenv); - assert(jclss == NULL); - } - - return jclss; + if (NULL == name) { + return NULL; + } + + const char* buf = GetStringUTFChars(jenv, name, NULL); + ClassLoaderHandle loader = class_loader_lookup(cl); + Class_Handle clss = class_find_loaded(loader, buf); + ReleaseStringUTFChars(jenv, name, buf); + + return clss ? jni_class_from_handle(jenv, clss) : NULL; } /* @@ -448,6 +408,7 @@ (JNIEnv *jenv, jclass unused, jclass clazz) { ASSERT_RAISE_AREA; + assert(clazz != NULL); Class *clss = jni_get_class_handle(jenv, clazz); Java_java_lang_VMClassRegistry_linkClass(jenv, unused, clazz); if(jenv->ExceptionCheck()) Index: vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.h =================================================================== --- vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.h (revision 509500) +++ vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.h (working copy) @@ -15,11 +15,6 @@ * limitations under the License. */ -/** - * @author Euguene Ostrovsky - * @version $Revision: 1.1.2.1.4.6 $ - */ - /* * THE FILE HAS BEEN AUTOGENERATED BY INTEL IJH TOOL. * Please be aware that all changes made to this file manually @@ -50,11 +45,12 @@ jstring, jobject, jbyteArray, jint, jint); /* - * Method: java.lang.VMClassRegistry.findLoadedClass(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/Class; + * Method: java.lang.VMClassRegistry.loadBootstrapClass(Ljava/lang/String;)Ljava/lang/Class; + * Throws: java.lang.NoClassDefFoundError */ JNIEXPORT jclass JNICALL -Java_java_lang_VMClassRegistry_findLoadedClass(JNIEnv *, jclass, - jstring, jobject); +Java_java_lang_VMClassRegistry_loadBootstrapClass(JNIEnv *, jclass, + jstring); /* * Method: java.lang.VMClassRegistry.getClass(Ljava/lang/Object;)Ljava/lang/Class; Index: vm/vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java (revision 509500) +++ vm/vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java (working copy) @@ -111,25 +111,13 @@ */ static native Class defineClass(String name, ClassLoader classLoader, byte[] data, int off, int len) throws ClassFormatError; - + /** - * This method satisfies the requirements of the specification for the - * {@link ClassLoader#findLoadedClass(String) - * ClassLoader.findLoadedClass(String name)} method. But it differs in - * several ways. - *

- * First, it takes additional class loader parameter. - *

- * Second, if the specified class loader is equal to null it should make an - * attempt to load a class with the specified name. If class can not be - * loaded by any reason null should be returned. - * - * @param loader the class loader which is used to find loaded classes. if - * the specified class loader is equal to null than the bootstrap - * class loader will be searched. + * Loads the specified class with the bootstrap classloader. + * @throws LinkageError (or any subtype) if loading failed * @api2vm */ - static native Class findLoadedClass(String name, ClassLoader loader); + static native Class loadBootstrapClass(String name); /** * This method satisfies the requirements of the specification for the Index: vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java (revision 509500) +++ vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java (working copy) @@ -134,9 +134,13 @@ */ public static Class forName(String name, boolean initialize, ClassLoader classLoader) throws ClassNotFoundException { - if (name == null) + if (name == null) { throw new NullPointerException(); - + } + if(name.indexOf("/") != -1) { + throw new ClassNotFoundException(name); + } + Class clazz = null; int i = 0; try { @@ -203,16 +207,13 @@ VMClassRegistry.getClassLoader(VMStack.getCallerClass(0)) != null) { sc.checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION); } - clazz = VMClassRegistry.findLoadedClass(name, null); - if (clazz == null) { - throw new ClassNotFoundException(name); - } + clazz = VMClassRegistry.loadBootstrapClass(name); } else { clazz = classLoader.loadClass(name); - if (clazz == null) { - throw new ClassNotFoundException(name); - } } + if(clazz == null) { + throw new ClassNotFoundException(name); + } if (i > 0) { clazz = VMClassRegistry.loadArray(clazz, i); } Index: vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (revision 509500) +++ vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (working copy) @@ -454,9 +454,7 @@ /** * @com.intel.drl.spec_ref */ - protected final Class findLoadedClass(String name) { - return VMClassRegistry.findLoadedClass(name, this); - } + protected final native Class findLoadedClass(String name); /** * @com.intel.drl.spec_ref @@ -521,15 +519,19 @@ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { checkInitialized(); + if (name == null) { + throw new NullPointerException(); + } + if(name.indexOf("/") != -1) { + throw new ClassNotFoundException(name); + } + Class clazz = findLoadedClass(name); if (clazz == null) { if (parentClassLoader == null) { - clazz = VMClassRegistry.findLoadedClass(name, null); + clazz = VMClassRegistry.loadBootstrapClass(name); } else { - try { - clazz = parentClassLoader.loadClass(name); - } catch (ClassNotFoundException e) { - } + clazz = parentClassLoader.loadClass(name); } if (clazz == null) { clazz = findClass(name); Index: vm/vmcore/src/class_support/classloader.cpp =================================================================== --- vm/vmcore/src/class_support/classloader.cpp (revision 509500) +++ vm/vmcore/src/class_support/classloader.cpp (working copy) @@ -236,6 +236,15 @@ return NULL; } } + if (LookupClass(className) != NULL) { + static const char* mess_templ = "Illegal attempt to redefine class : %s"; + unsigned mess_size = strlen(mess_templ) + className->len + 1; + char* err_mess = (char*)STD_ALLOCA(mess_size); + sprintf(err_mess, mess_templ, className->bytes); + exn_raise_by_name("java/lang/LinkageError", err_mess); + return NULL; + } + if(res_name) { *res_name = className; } @@ -293,7 +302,9 @@ } } // XXX - + + p_TLS_vmthread->is_original = false; + if(!clss->load_ancestors(env)) { FailedLoadingClass(className); return NULL; @@ -1684,7 +1695,7 @@ // the symptom of circularity (illegal) is that a null class name is passed, // so detect this immediately - if( !class_name->bytes || *(class_name->bytes) == 0 ) { + if(!class_name->bytes) { REPORT_FAILED_CLASS_NAME(this, class_name->bytes, "java/lang/ClassCircularityError", class_name->bytes); return NULL;