123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- // natVMClassLoader.cc - VMClassLoader native methods
- /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
- This file is part of libgcj.
- This software is copyrighted work licensed under the terms of the
- Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
- details. */
- /* Author: Kresten Krab Thorup <krab@gnu.org> */
- #include <config.h>
- #include <stdlib.h>
- #include <string.h>
- #include <gcj/cni.h>
- #include <jvm.h>
- #include <java-threads.h>
- #include <java-interp.h>
- #include <java/lang/VMClassLoader.h>
- #include <java/lang/VMCompiler.h>
- #include <gnu/gcj/runtime/ExtensionClassLoader.h>
- #include <gnu/gcj/runtime/SystemClassLoader.h>
- #include <gnu/gcj/runtime/BootClassLoader.h>
- #include <java/lang/ClassLoader.h>
- #include <java/lang/Class.h>
- #include <java/lang/Throwable.h>
- #include <java/security/ProtectionDomain.h>
- #include <java/lang/ClassFormatError.h>
- #include <java/lang/StringBuffer.h>
- #include <java/lang/SecurityManager.h>
- #include <java/lang/Runtime.h>
- #include <java/util/HashSet.h>
- #include <java/lang/SecurityException.h>
- #include <java/lang/VirtualMachineError.h>
- java::lang::Class *
- java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
- jstring name,
- jbyteArray data,
- jint offset,
- jint length,
- java::security::ProtectionDomain *pd)
- {
- jclass klass = VMCompiler::compileClass(loader, name, data,
- offset, length, pd);
- if (klass)
- _Jv_RegisterInitiatingLoader (klass, klass->loader);
- #ifdef INTERPRETER
- if (klass == NULL)
- {
- klass = new java::lang::Class ();
- // Synchronize on the class, so that it is not attempted initialized
- // until we're done loading.
- JvSynchronize sync (klass);
- // Record the defining loader. For the bootstrap class loader,
- // we record NULL.
- if (loader != bootLoader)
- klass->loader = loader;
- if (name != 0)
- {
- _Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
- if (! _Jv_VerifyClassName (name2))
- throw new java::lang::ClassFormatError
- (JvNewStringLatin1 ("erroneous class name"));
- klass->name = name2;
- }
- _Jv_Utf8Const *found_name = NULL;
- try
- {
- _Jv_DefineClass (klass, data, offset, length, pd, &found_name);
- }
- catch (java::lang::Throwable *ex)
- {
- klass->state = JV_STATE_ERROR;
- klass->notifyAll ();
- if (found_name != NULL)
- _Jv_UnregisterInitiatingLoader (klass, klass->loader);
- // If EX is not a ClassNotFoundException, that's ok, because we
- // account for the possibility in defineClass().
- throw ex;
- }
- // if everything proceeded sucessfully, we're loaded.
- JvAssert (klass->state == JV_STATE_READ);
- }
- #endif // INTERPRETER
- if (! klass)
- {
- StringBuffer *sb = new StringBuffer();
- if (name)
- {
- sb->append(JvNewStringLatin1("found class file for class "));
- sb->append(name);
- }
- else
- sb->append(JvNewStringLatin1("found unnamed class file"));
- sb->append(JvNewStringLatin1(", but no interpreter configured in this libgcj"));
- throw new VirtualMachineError(sb->toString());
- }
- return klass;
- }
- java::lang::ClassLoader *
- java::lang::VMClassLoader::getSystemClassLoaderInternal()
- {
- _Jv_InitClass (&gnu::gcj::runtime::ExtensionClassLoader::class$);
- _Jv_CopyClassesToSystemLoader (gnu::gcj::runtime::ExtensionClassLoader::system_instance);
- return gnu::gcj::runtime::ExtensionClassLoader::system_instance;
- }
- jclass
- java::lang::VMClassLoader::getPrimitiveClass (jchar type)
- {
- char sig[2];
- sig[0] = (char) type;
- sig[1] = '\0';
- // Note: this cannot return NULL, since the input is always correct.
- return _Jv_FindClassFromSignature (sig, NULL);
- }
- void
- java::lang::VMClassLoader::initBootLoader(jstring libdir)
- {
- bootLoader = new gnu::gcj::runtime::BootClassLoader(libdir);
- }
- jclass
- java::lang::VMClassLoader::nativeFindClass (jstring name)
- {
- jclass klass = NULL;
- if (lib_control != LIB_NEVER)
- {
- // Turn `gnu.pkg.quux' into `lib-gnu-pkg-quux'. Then search for
- // a module named (eg, on Linux) `lib-gnu-pkg-quux.so', followed
- // by `lib-gnu-pkg.so' and `lib-gnu.so'. If loading one of
- // these causes the class to appear in the cache, then use it.
- java::lang::StringBuffer *sb
- = new java::lang::StringBuffer (JvNewStringLatin1("lib-"));
- // Skip inner classes
- jstring cn;
- jint ci = name->indexOf('$');
- if (ci == -1)
- cn = name;
- else
- cn = name->substring (0, ci);
- jstring so_base_name
- = (sb->append (cn)->toString ())->replace ('.', '-');
- using namespace ::java::lang;
- Runtime *rt = Runtime::getRuntime();
- _Jv_Utf8Const *name_u = NULL;
- // Compare against `3' because that is the length of "lib".
- while (! klass && so_base_name && so_base_name->length() > 3)
- {
- if (lib_control == LIB_CACHE)
- {
- // If we've already tried this name, we're done.
- if (tried_libraries->contains(so_base_name))
- break;
- tried_libraries->add(so_base_name);
- }
- jboolean loaded = rt->loadLibraryInternal (so_base_name);
- jint nd = so_base_name->lastIndexOf ('-');
- if (nd == -1)
- so_base_name = NULL;
- else
- so_base_name = so_base_name->substring (0, nd);
- if (loaded)
- {
- if (name_u == NULL)
- name_u = _Jv_makeUtf8Const (name);
- klass = _Jv_FindClassInCache (name_u);
- }
- }
- }
- if (klass)
- definePackageForNative(name);
- return klass;
- }
- jclass
- java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
- {
- using namespace ::java::lang;
- SecurityManager *sm = (SecurityManager *)SecurityManager::current;
- if (sm)
- {
- jint lastDot = name->lastIndexOf('.');
- if (lastDot != -1)
- sm->checkPackageAccess(name->substring(0, lastDot));
- }
- // We try the boot loader first, so that the endorsed directory
- // overrides compiled-in classes.
- jclass klass = NULL;
- if (bootLoader)
- klass = bootLoader->bootLoadClass(name);
- if (! klass)
- {
- _Jv_Utf8Const *utf = _Jv_makeUtf8Const (name);
- klass = _Jv_FindClassInCache (utf);
- }
- if (! klass)
- klass = nativeFindClass(name);
- if (klass)
- {
- // We never want to return a class without its supers linked.
- // It isn't clear from the spec, but this is what other
- // implementations do in practice.
- if (resolve)
- resolveClass (klass);
- else
- _Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
- definePackageForNative(name);
- }
- return klass;
- }
|