class_linker.h revision 9cff8e13d41825c4f3f0127af061e94b06114fc8
10e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro// Copyright 2011 Google Inc. All Rights Reserved. 20e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 30e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#ifndef ART_SRC_CLASS_LINKER_H_ 40e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#define ART_SRC_CLASS_LINKER_H_ 50e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 60e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#include <map> 70e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#include <utility> 80e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#include <vector> 90e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 107e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "dex_file.h" 114a96b60e45fba4a9d4a2e9c8fc849660eacef684Brian Carlstrom#include "heap.h" 127e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "intern_table.h" 13578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "macros.h" 14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "object.h" 157e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "thread.h" 167e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "unordered_map.h" 177e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 18578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "gtest/gtest.h" 190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapironamespace art { 210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 220e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass ClassLinker { 230e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public: 24565f50731db360584d0080af7f14f0b7ca10371cCarl Shapiro // Initializes the class linker. 252ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro static ClassLinker* Create(const std::vector<DexFile*>& boot_class_path); 2661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 27de69d7f8c32be83c405bf5a9c5f15fc655f578faElliott Hughes ~ClassLinker() { 28de69d7f8c32be83c405bf5a9c5f15fc655f578faElliott Hughes delete classes_lock_; 29de69d7f8c32be83c405bf5a9c5f15fc655f578faElliott Hughes } 30565f50731db360584d0080af7f14f0b7ca10371cCarl Shapiro 310e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro // Finds a class by its descriptor name. 3274eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom // If class_loader is null, searches boot_class_path_. 336cc18456b6d0d1348ad1d64116b7ab78108ff814Brian Carlstrom Class* FindClass(const StringPiece& descriptor, 3474eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom ClassLoader* class_loader); 350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 36d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes Class* FindPrimitiveClass(char type); 37d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes 386cc18456b6d0d1348ad1d64116b7ab78108ff814Brian Carlstrom Class* FindSystemClass(const StringPiece& descriptor) { 3974eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom return FindClass(descriptor, NULL); 40565f50731db360584d0080af7f14f0b7ca10371cCarl Shapiro } 41565f50731db360584d0080af7f14f0b7ca10371cCarl Shapiro 42f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes // Returns true on success, false if there's an exception pending. 43f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes bool EnsureInitialized(Class* c); 440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 454a96b60e45fba4a9d4a2e9c8fc849660eacef684Brian Carlstrom void RegisterDexFile(const DexFile* dex_file); 460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 477e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom void VisitRoots(Heap::RootVistor* root_visitor, void* arg); 4875cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom 490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private: 50d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes ClassLinker() 51d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes : classes_lock_(Mutex::Create("ClassLinker::Lock")), 52d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes init_done_(false) { 537e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom } 5461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 552ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro void Init(const std::vector<DexFile*>& boot_class_path_); 5661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 57f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes bool InitializeClass(Class* klass); 58f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes 5975cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom // For early bootstrapping by Init 6075cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom Class* AllocClass(Class* java_lang_Class); 6175cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom 6275cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom // Alloc* convenience functions to avoid needing to pass in Class* 6375cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom // values that are known to the ClassLinker such as 6475cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom // kObjectArrayClass and kJavaLangString etc. 6575cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom Class* AllocClass(); 6675cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom DexCache* AllocDexCache(); 6735baaab2a79014f35e225b189f6dbec1b4ba9542Jesse Wilson Field* AllocField(); 6875cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom Method* AllocMethod(); 6975cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom template <class T> 7075cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom ObjectArray<T>* AllocObjectArray(size_t length) { 7175cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom return ObjectArray<T>::Alloc(class_roots_->Get(kObjectArrayClass), length); 7275cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom } 7374eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom PathClassLoader* AllocPathClassLoader(std::vector<const DexFile*> dex_files); 7475cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom 759cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom Class* CreatePrimitiveClass(const char* descriptor); 76a331b3cc392132c7333d36649a8310f38f4822ccBrian Carlstrom 77578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom Class* CreateArrayClass(const StringPiece& descriptor, 7874eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom ClassLoader* class_loader); 79578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 8074eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom const DexFile& FindDexFile(const DexCache* dex_cache) const; 81578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 82f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom DexCache* FindDexCache(const DexFile* dex_file) const; 83578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 84f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom void AppendToBootClassPath(DexFile* dex_file); 85578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 86f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom void LoadClass(const DexFile& dex_file, 87f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom const DexFile::ClassDef& dex_class_def, 8874eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom Class* klass, 8974eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom ClassLoader* class_loader); 90565f50731db360584d0080af7f14f0b7ca10371cCarl Shapiro 91f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom void LoadInterfaces(const DexFile& dex_file, 92f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom const DexFile::ClassDef& dex_class_def, 93578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom Class *klass); 94934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom 95f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom void LoadField(const DexFile& dex_file, 96f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom const DexFile::Field& dex_field, 97578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom Class* klass, 98578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom Field* dst); 99934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom 100f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom void LoadMethod(const DexFile& dex_file, 101f615a61aef972cfc1dc23931ac2ed0da14c3fedbBrian Carlstrom const DexFile::Method& dex_method, 102578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom Class* klass, 103578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom Method* dst); 104934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom 1057e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom Class* ResolveClass(const Class* referring, 1067e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom uint32_t class_idx, 1077e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom const DexFile& dex_file); 1087e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 1097e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom String* ResolveString(const Class* referring, 1107e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom uint32_t string_idx, 1117e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom const DexFile& dex_file); 1127e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 1137e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom Class* LookupClass(const StringPiece& descriptor, ClassLoader* class_loader); 1147e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 1150e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro // Inserts a class into the class table. Returns true if the class 1160e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro // was inserted. 1179cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom bool InsertClass(const StringPiece& descriptor, Class* klass); 1180e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool InitializeSuperClass(Class* klass); 1200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro void InitializeStaticFields(Class* klass); 1220e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1230e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool ValidateSuperClassDescriptors(const Class* klass); 1240e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1250e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool HasSameDescriptorClasses(const char* descriptor, 1260e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro const Class* klass1, 1270e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro const Class* klass2); 1280e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1290e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool HasSameMethodDescriptorClasses(const Method* descriptor, 1300e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro const Class* klass1, 1310e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro const Class* klass2); 1320e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 13374eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom bool LinkClass(Class* klass, const DexFile& dex_file); 1340e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool LinkSuperClass(Class* klass); 1360e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 13774eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom bool LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file); 1380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool LinkMethods(Class* klass); 1400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool LinkVirtualMethods(Class* klass); 1420e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool LinkInterfaceMethods(Class* klass); 1440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro void LinkAbstractMethods(Class* klass); 1460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1477833bd261d78be2c42284031f169a62c9065cc3cJesse Wilson bool LinkStaticFields(Class* klass); 1487833bd261d78be2c42284031f169a62c9065cc3cJesse Wilson 1490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool LinkInstanceFields(Class* klass); 1500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro void CreateReferenceOffsets(Class* klass); 1520e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1534a96b60e45fba4a9d4a2e9c8fc849660eacef684Brian Carlstrom std::vector<const DexFile*> boot_class_path_; 154578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 1554a96b60e45fba4a9d4a2e9c8fc849660eacef684Brian Carlstrom std::vector<const DexFile*> dex_files_; 156578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom 1577e49dca262933bc30cbc8b9f07cfc8cce2343389Brian Carlstrom std::vector<DexCache*> dex_caches_; 1580e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1599cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom // multimap from a StringPiece hash code of a class descriptor to 1609cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom // Class* instances. Results should be compared for a matching 1619cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom // Class::descriptor_ and Class::class_loader_. 1629cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom typedef std::tr1::unordered_multimap<size_t, Class*> Table; 1630e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro Table classes_; 1640e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro Mutex* classes_lock_; 1650e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1667e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom InternTable intern_table_; 1670e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 16875cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom // indexes into class_roots_ 16974eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom enum ClassRoot { 17075cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kJavaLangClass, 17175cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kJavaLangObject, 17274eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom kObjectArrayClass, 17374eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom kJavaLangString, 17475cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kJavaLangReflectField, 17575cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kJavaLangReflectMethod, 17674eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom kJavaLangClassLoader, 17774eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom kDalvikSystemBaseDexClassLoader, 17874eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom kDalvikSystemPathClassLoader, 17975cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kPrimitiveBoolean, 180d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kPrimitiveByte, 18175cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kPrimitiveChar, 18275cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kPrimitiveDouble, 183d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kPrimitiveFloat, 18475cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kPrimitiveInt, 18575cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kPrimitiveLong, 186d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kPrimitiveShort, 18775cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kPrimitiveVoid, 188d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kBooleanArrayClass, 189d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kByteArrayClass, 190d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kCharArrayClass, 191d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kDoubleArrayClass, 192d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kFloatArrayClass, 193d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kIntArrayClass, 194d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kLongArrayClass, 195d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes kShortArrayClass, 19675cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom kClassRootsMax, 19775cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom }; 19875cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom ObjectArray<Class>* class_roots_; 199913af1bd90a6e8fd56f1f851db1f098636dae6a5Brian Carlstrom 20074eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom Class* GetClassRoot(ClassRoot class_root) { 20174eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom Class* klass = class_roots_->Get(class_root); 20274eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom DCHECK(klass != NULL); 20374eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom return klass; 20474eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom } 20574eb46ab15c5b9cb39bf15246db84aea7fd4cc27Brian Carlstrom 2064a96b60e45fba4a9d4a2e9c8fc849660eacef684Brian Carlstrom ObjectArray<Class>* array_interfaces_; 207913af1bd90a6e8fd56f1f851db1f098636dae6a5Brian Carlstrom InterfaceEntry* array_iftable_; 208565f50731db360584d0080af7f14f0b7ca10371cCarl Shapiro 20975cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom bool init_done_; 21075cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom 211f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstrom friend class CommonTest; 21275cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom FRIEND_TEST(DexCacheTest, Open); 21375cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom friend class ObjectTest; 21475cb3b477be3757a0351fb6ab1cb70751a71e2bfBrian Carlstrom FRIEND_TEST(ObjectTest, AllocObjectArray); 2152fb9753c58ce1a511fd6996856840120eb2930dbShih-wei Liao FRIEND_TEST(ExceptionTest, MyClass_F_G); 2160e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro DISALLOW_COPY_AND_ASSIGN(ClassLinker); 2170e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}; 2180e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 2190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro} // namespace art 2200e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 2210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif // ART_SRC_CLASS_LINKER_H_ 222