class_linker.h revision b63ec393a5c4ba2be1d34dd871cda811eaa803c7
1// Copyright 2011 Google Inc. All Rights Reserved.
2
3#ifndef ART_SRC_CLASS_LINKER_H_
4#define ART_SRC_CLASS_LINKER_H_
5
6#include <map>
7#include <utility>
8#include <vector>
9
10#include "dex_file.h"
11#include "heap.h"
12#include "intern_table.h"
13#include "macros.h"
14#include "object.h"
15#include "thread.h"
16#include "unordered_map.h"
17#include "unordered_set.h"
18
19#include "gtest/gtest.h"
20
21namespace art {
22
23class ClassLinker {
24 public:
25  // Initializes the class linker using DexFile and an optional boot Space.
26  static ClassLinker* Create(const std::vector<const DexFile*>& boot_class_path, Space* boot_space);
27
28  ~ClassLinker();
29
30  // Finds a class by its descriptor name.
31  // If class_loader is null, searches boot_class_path_.
32  Class* FindClass(const StringPiece& descriptor,
33                   const ClassLoader* class_loader);
34
35  Class* FindPrimitiveClass(char type);
36
37  Class* FindSystemClass(const StringPiece& descriptor) {
38    return FindClass(descriptor, NULL);
39  }
40
41  size_t NumLoadedClasses() const;
42
43  // Resolve a String with the given index from the DexFile, storing the
44  // result in the DexCache.
45  String* ResolveString(const DexFile& dex_file,
46                        uint32_t string_idx,
47                        DexCache* dex_cache);
48
49  // Resolve a Type with the given index from the DexFile, storing the
50  // result in the DexCache. The referrer is used to identity the
51  // target DexCache and ClassLoader to use for resolution.
52  Class* ResolveType(const DexFile& dex_file,
53                     uint32_t type_idx,
54                     const Class* referrer) {
55    return ResolveType(dex_file,
56                       type_idx,
57                       referrer->GetDexCache(),
58                       referrer->GetClassLoader());
59  }
60
61  // Resolve a Type with the given index from the DexFile, storing the
62  // result in the DexCache. The referrer is used to identity the
63  // target DexCache and ClassLoader to use for resolution.
64  Class* ResolveType(uint32_t type_idx, Method* referrer) {
65    Class* declaring_class = referrer->GetDeclaringClass();
66    DexCache* dex_cache = declaring_class->GetDexCache();
67    const ClassLoader* class_loader = declaring_class->GetClassLoader();
68    const DexFile& dex_file = FindDexFile(dex_cache);
69    return ResolveType(dex_file, type_idx, dex_cache, class_loader);
70  }
71
72  // Resolve a type with the given ID from the DexFile, storing the
73  // result in DexCache. The ClassLoader is used to search for the
74  // type, since it may be referenced from but not contained within
75  // the given DexFile.
76  Class* ResolveType(const DexFile& dex_file,
77                     uint32_t type_idx,
78                     DexCache* dex_cache,
79                     const ClassLoader* class_loader);
80
81  // Resolve a method with a given ID from the DexFile, storing the
82  // result in DexCache. The ClassLinker and ClassLoader are used as
83  // in ResolveType. What is unique is the method type argument which
84  // is used to determine if this method is a direct, static, or
85  // virtual method.
86  Method* ResolveMethod(const DexFile& dex_file,
87                        uint32_t method_idx,
88                        DexCache* dex_cache,
89                        const ClassLoader* class_loader,
90                        bool is_direct);
91
92  // Resolve a method with a given ID from the DexFile, storing the
93  // result in DexCache. The ClassLinker and ClassLoader are used as
94  // in ResolveType. What is unique is the is_static argument which is
95  // used to determine if we are resolving a static or non-static
96  // field.
97  Field* ResolveField(const DexFile& dex_file,
98                      uint32_t field_idx,
99                      DexCache* dex_cache,
100                      const ClassLoader* class_loader,
101                      bool is_static);
102
103  // Returns true on success, false if there's an exception pending.
104  bool EnsureInitialized(Class* c);
105
106  void RegisterDexFile(const DexFile& dex_file);
107  void RegisterDexFile(const DexFile& dex_file, DexCache* dex_cache);
108
109  const InternTable& GetInternTable() {
110    return intern_table_;
111  }
112
113  void VisitRoots(Heap::RootVistor* root_visitor, void* arg) const;
114
115  const DexFile& FindDexFile(const DexCache* dex_cache) const;
116  DexCache* FindDexCache(const DexFile& dex_file) const;
117
118  ObjectArray<StackTraceElement>* AllocStackTraceElementArray(size_t length);
119
120 private:
121  ClassLinker();
122
123  // Initialize class linker from DexFile instances.
124  void Init(const std::vector<const DexFile*>& boot_class_path_);
125
126  // Initialize class linker from pre-initialized space.
127  void Init(const std::vector<const DexFile*>& boot_class_path_, Space* space);
128  static void InitCallback(Object* obj, void *arg);
129  struct InitCallbackState;
130
131  void FinishInit();
132
133  bool InitializeClass(Class* klass);
134
135  // For early bootstrapping by Init
136  Class* AllocClass(Class* java_lang_Class, size_t class_size);
137
138  // Alloc* convenience functions to avoid needing to pass in Class*
139  // values that are known to the ClassLinker such as
140  // kObjectArrayClass and kJavaLangString etc.
141  Class* AllocClass(size_t class_size);
142  DexCache* AllocDexCache(const DexFile& dex_file);
143  Field* AllocField();
144  Method* AllocMethod();
145  template <class T>
146  ObjectArray<T>* AllocObjectArray(size_t length) {
147    return ObjectArray<T>::Alloc(GetClassRoot(kObjectArrayClass), length);
148  }
149  CodeAndMethods* AllocCodeAndMethods(size_t length);
150
151  Class* CreatePrimitiveClass(const char* descriptor);
152
153  Class* CreateArrayClass(const StringPiece& descriptor,
154                          const ClassLoader* class_loader);
155
156  void AppendToBootClassPath(const DexFile& dex_file);
157  void AppendToBootClassPath(const DexFile& dex_file, DexCache* dex_cache);
158
159  size_t SizeOfClass(const DexFile& dex_file,
160                     const DexFile::ClassDef& dex_class_def);
161
162  void LoadClass(const DexFile& dex_file,
163                 const DexFile::ClassDef& dex_class_def,
164                 Class* klass,
165                 const ClassLoader* class_loader);
166
167  void LoadInterfaces(const DexFile& dex_file,
168                      const DexFile::ClassDef& dex_class_def,
169                      Class *klass);
170
171  void LoadField(const DexFile& dex_file,
172                 const DexFile::Field& dex_field,
173                 Class* klass,
174                 Field* dst);
175
176  void LoadMethod(const DexFile& dex_file,
177                  const DexFile::Method& dex_method,
178                  Class* klass,
179                  Method* dst);
180
181  Class* LookupClass(const StringPiece& descriptor, const ClassLoader* class_loader);
182
183  // Inserts a class into the class table.  Returns true if the class
184  // was inserted.
185  bool InsertClass(const StringPiece& descriptor, Class* klass);
186
187  bool InitializeSuperClass(Class* klass);
188
189  void InitializeStaticFields(Class* klass);
190
191  bool ValidateSuperClassDescriptors(const Class* klass);
192
193  bool HasSameDescriptorClasses(const char* descriptor,
194                                const Class* klass1,
195                                const Class* klass2);
196
197  bool HasSameMethodDescriptorClasses(const Method* descriptor,
198                                      const Class* klass1,
199                                      const Class* klass2);
200
201  bool LinkClass(Class* klass, const DexFile& dex_file);
202
203  bool LinkSuperClass(Class* klass);
204
205  bool LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file);
206
207  bool LinkMethods(Class* klass);
208
209  bool LinkVirtualMethods(Class* klass);
210
211  bool LinkInterfaceMethods(Class* klass);
212
213  void LinkAbstractMethods(Class* klass);
214
215  bool LinkStaticFields(Class* klass);
216  bool LinkInstanceFields(Class* klass);
217  bool LinkFields(size_t field_offset,
218                  size_t& num_reference_fields,
219                  size_t num_fields,
220                  ObjectArray<Field>* fields,
221                  size_t& size);
222
223  void CreateReferenceInstanceOffsets(Class* klass);
224  void CreateReferenceStaticOffsets(Class* klass);
225  void CreateReferenceOffsets(uint32_t& reference_offsets,
226                              size_t num_reference_fields,
227                              const ObjectArray<Field>* fields);
228
229  std::vector<const DexFile*> boot_class_path_;
230
231  std::vector<const DexFile*> dex_files_;
232
233  std::vector<DexCache*> dex_caches_;
234
235  // multimap from a StringPiece hash code of a class descriptor to
236  // Class* instances. Results should be compared for a matching
237  // Class::descriptor_ and Class::class_loader_.
238  typedef std::tr1::unordered_multimap<size_t, Class*> Table;
239  Table classes_;
240  Mutex* classes_lock_;
241
242  InternTable intern_table_;
243
244  // indexes into class_roots_.
245  // needs to be kept in sync with class_roots_descriptors_.
246  enum ClassRoot {
247    kJavaLangClass,
248    kJavaLangObject,
249    kObjectArrayClass,
250    kJavaLangString,
251    kJavaLangReflectField,
252    kJavaLangReflectMethod,
253    kJavaLangClassLoader,
254    kDalvikSystemBaseDexClassLoader,
255    kDalvikSystemPathClassLoader,
256    kJavaLangStackTraceElement,
257    kPrimitiveBoolean,
258    kPrimitiveByte,
259    kPrimitiveChar,
260    kPrimitiveDouble,
261    kPrimitiveFloat,
262    kPrimitiveInt,
263    kPrimitiveLong,
264    kPrimitiveShort,
265    kPrimitiveVoid,
266    kBooleanArrayClass,
267    kByteArrayClass,
268    kCharArrayClass,
269    kDoubleArrayClass,
270    kFloatArrayClass,
271    kIntArrayClass,
272    kLongArrayClass,
273    kShortArrayClass,
274    kJavaLangStackTraceElementArrayClass,
275    kClassRootsMax,
276  };
277  ObjectArray<Class>* class_roots_;
278
279  Class* GetClassRoot(ClassRoot class_root) {
280    DCHECK(class_roots_ != NULL);
281    Class* klass = class_roots_->Get(class_root);
282    DCHECK(klass != NULL);
283    return klass;
284  }
285
286  void SetClassRoot(ClassRoot class_root, Class* klass) {
287    DCHECK(!init_done_);
288
289    DCHECK(klass != NULL);
290    DCHECK(klass->class_loader_ == NULL);
291    DCHECK(klass->descriptor_ != NULL);
292    DCHECK(klass->descriptor_->Equals(GetClassRootDescriptor(class_root)));
293
294    DCHECK(class_roots_ != NULL);
295    DCHECK(class_roots_->Get(class_root) == NULL);
296    class_roots_->Set(class_root, klass);
297  }
298
299  static const char* class_roots_descriptors_[kClassRootsMax];
300
301  const char* GetClassRootDescriptor(ClassRoot class_root) {
302    const char* descriptor = class_roots_descriptors_[class_root];
303    CHECK(descriptor != NULL);
304    return descriptor;
305  }
306
307  ObjectArray<Class>* array_interfaces_;
308  InterfaceEntry* array_iftable_;
309
310  bool init_done_;
311
312  friend class CommonTest;
313  FRIEND_TEST(DexCacheTest, Open);
314  friend class ObjectTest;
315  FRIEND_TEST(ObjectTest, AllocObjectArray);
316  FRIEND_TEST(ExceptionTest, FindExceptionHandler);
317  DISALLOW_COPY_AND_ASSIGN(ClassLinker);
318};
319
320}  // namespace art
321
322#endif  // ART_SRC_CLASS_LINKER_H_
323