OSDN Git Service

2006-08-14 Mark Wielaard <mark@klomp.org>
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natVMClassLoader.cc
1 // natVMClassLoader.cc - VMClassLoader native methods
2
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
12
13 #include <config.h>
14
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include <gcj/cni.h>
19 #include <jvm.h>
20
21 #include <java-threads.h>
22 #include <java-interp.h>
23
24 #include <java/lang/VMClassLoader.h>
25 #include <java/lang/VMCompiler.h>
26 #include <gnu/gcj/runtime/ExtensionClassLoader.h>
27 #include <gnu/gcj/runtime/SystemClassLoader.h>
28 #include <gnu/gcj/runtime/BootClassLoader.h>
29 #include <java/lang/ClassLoader.h>
30 #include <java/lang/Class.h>
31 #include <java/lang/Throwable.h>
32 #include <java/security/ProtectionDomain.h>
33 #include <java/lang/ClassFormatError.h>
34 #include <java/lang/StringBuffer.h>
35 #include <java/lang/Runtime.h>
36 #include <java/util/HashSet.h>
37 #include <java/lang/VirtualMachineError.h>
38
39 java::lang::Class *
40 java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
41                                         jstring name,
42                                         jbyteArray data, 
43                                         jint offset,
44                                         jint length,
45                                         java::security::ProtectionDomain *pd)
46 {
47   jclass klass = VMCompiler::compileClass(loader, name, data,
48                                           offset, length, pd);
49
50 #ifdef INTERPRETER
51   if (klass == NULL)
52     {
53       klass = new java::lang::Class ();
54
55       // Synchronize on the class, so that it is not attempted initialized
56       // until we're done loading.
57       JvSynchronize sync (klass);
58
59       // Record the defining loader.  For the bootstrap class loader,
60       // we record NULL.
61       if (loader != bootLoader)
62         klass->loader = loader;
63
64       if (name != 0)
65         {
66           _Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
67
68           if (! _Jv_VerifyClassName (name2))
69             throw new java::lang::ClassFormatError
70               (JvNewStringLatin1 ("erroneous class name"));
71
72           klass->name = name2;
73         }
74
75       _Jv_Utf8Const *found_name = NULL;
76       try
77         {
78           _Jv_DefineClass (klass, data, offset, length, pd, &found_name);
79         }
80       catch (java::lang::Throwable *ex)
81         {
82           klass->state = JV_STATE_ERROR;
83           klass->notifyAll ();
84
85           if (found_name != NULL)
86             _Jv_UnregisterInitiatingLoader (klass, klass->loader);
87
88           // If EX is not a ClassNotFoundException, that's ok, because we
89           // account for the possibility in defineClass().
90           throw ex;
91         }
92
93       // if everything proceeded sucessfully, we're loaded.
94       JvAssert (klass->state == JV_STATE_LOADED);
95     }
96 #endif // INTERPRETER
97
98   if (! klass)
99     {
100       StringBuffer *sb = new StringBuffer();
101       if (name)
102         {
103           sb->append(JvNewStringLatin1("found class file for class "));
104           sb->append(name);
105         }
106       else
107         sb->append(JvNewStringLatin1("found unnamed class file"));
108       sb->append(JvNewStringLatin1(", but no interpreter configured in this libgcj"));
109       throw new VirtualMachineError(sb->toString());
110     }
111
112   return klass;
113 }
114
115 java::lang::ClassLoader *
116 java::lang::VMClassLoader::getSystemClassLoaderInternal()
117 {
118   _Jv_InitClass (&gnu::gcj::runtime::ExtensionClassLoader::class$);
119   _Jv_CopyClassesToSystemLoader (gnu::gcj::runtime::ExtensionClassLoader::system_instance);
120   return gnu::gcj::runtime::ExtensionClassLoader::system_instance;
121 }
122
123 jclass
124 java::lang::VMClassLoader::getPrimitiveClass (jchar type)
125 {
126   char sig[2];
127   sig[0] = (char) type;
128   sig[1] = '\0';
129   // Note: this cannot return NULL, since the input is always correct.
130   return _Jv_FindClassFromSignature (sig, NULL);
131 }
132
133 void
134 java::lang::VMClassLoader::initBootLoader(jstring libdir)
135 {
136   bootLoader = new gnu::gcj::runtime::BootClassLoader(libdir);
137 }
138
139 jclass
140 java::lang::VMClassLoader::nativeFindClass (jstring name)
141 {
142   jclass klass = NULL;
143
144   if (lib_control != LIB_NEVER)
145     {
146       // Turn `gnu.pkg.quux' into `lib-gnu-pkg-quux'.  Then search for
147       // a module named (eg, on Linux) `lib-gnu-pkg-quux.so', followed
148       // by `lib-gnu-pkg.so' and `lib-gnu.so'.  If loading one of
149       // these causes the class to appear in the cache, then use it.
150       java::lang::StringBuffer *sb
151         = new java::lang::StringBuffer (JvNewStringLatin1("lib-"));
152       // Skip inner classes
153       jstring cn;
154       jint ci = name->indexOf('$');
155       if (ci == -1)
156         cn = name;
157       else
158         cn = name->substring (0, ci);
159       jstring so_base_name
160         = (sb->append (cn)->toString ())->replace ('.', '-');
161
162       using namespace ::java::lang;
163       Runtime *rt = Runtime::getRuntime();
164
165       _Jv_Utf8Const *name_u = NULL;
166
167       // Compare against `3' because that is the length of "lib".
168       while (! klass && so_base_name && so_base_name->length() > 3)
169         {
170           if (lib_control == LIB_CACHE)
171             {
172               // If we've already tried this name, we're done.
173               if (tried_libraries->contains(so_base_name))
174                 break;
175               tried_libraries->add(so_base_name);
176             }
177
178           jboolean loaded = rt->loadLibraryInternal (so_base_name);
179
180           jint nd = so_base_name->lastIndexOf ('-');
181           if (nd == -1)
182             so_base_name = NULL;
183           else
184             so_base_name = so_base_name->substring (0, nd);
185
186           if (loaded)
187             {
188               if (name_u == NULL)
189                 name_u = _Jv_makeUtf8Const (name);
190               klass = _Jv_FindClassInCache (name_u);
191             }
192         }
193     }
194
195   if (klass)
196     definePackageForNative(name);
197
198   return klass;
199 }
200
201 jclass
202 java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
203 {
204   // We try the boot loader first, so that the endorsed directory
205   // overrides compiled-in classes.
206   jclass klass = NULL;
207   if (bootLoader)
208     klass = bootLoader->bootLoadClass(name);
209   if (! klass)
210     {
211       _Jv_Utf8Const *utf = _Jv_makeUtf8Const (name);
212       klass = _Jv_FindClassInCache (utf);
213     }
214   if (! klass)
215     klass = nativeFindClass(name);
216   if (klass)
217     {
218       // We never want to return a class without its supers linked.
219       // It isn't clear from the spec, but this is what other
220       // implementations do in practice.
221       if (resolve)
222         resolveClass (klass);
223       else
224         _Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
225
226       definePackageForNative(name);
227     }
228
229   return klass;
230 }