mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			246 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			246 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
// 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;
 | 
						|
}
 |