Make ClassLinker set Class::super_class_ plus test and build improvements

Create placeholder ClassLinker::java_lang_Object_ for use a
super-class of java_lang_Class_ instances.

	src/class_linker.cc
	src/class_linker.h

Expand ClassLinker FindClass test to verify Class::GetSuperClass

	src/class_linker_test.cc

Move DexFile::Load* methods to ClassLinker so they can reference
java_lang_Object_ and java_lang_Class_

	src/class_linker.cc
	src/class_linker.h
	src/dex_file.cc
	src/dex_file.h

Move corresponding Load tests from class_linker_test to dex_file_test

	src/class_linker_test.cc
	src/dex_file_test.cc

Tracking change to object_test to use ClassLinker::Load* methods

	src/object_test.cc

Move base64 to new src/common_test.h for reuse accross tests. Add
missing example source for MyClass dex.

	src/common_test.h
	src/class_linker_test.cc
	src/dex_file_test.cc
	src/object_test.cc

Change Heap::AllocClass to take DexFile argument

	src/heap.h

Remove Method::dex_file_ in favor of using Method::GetClass::GetDexFile

	src/object.cc
	src/object.h

Made a few more RawDexFile methods const

	src/raw_dex_file.cc
	src/raw_dex_file.h

Add convenience targets for build-art and test-art-host

	Android.mk

Drop use of _LOCAL_ from make variants, which isn't the appropriate
here, where we aren't differentiating between LOCAL_ and PRIVATE_.
Avoid redefinition of variables based on now removed
LIBART_TARGET_ARCH and TEST_TARGET_ARCH to support phony targets in
Android.mk

	build/Android.aexec.host.mk
	build/Android.aexec.mk
	build/Android.common.mk
	build/Android.libart.host.mk
	build/Android.libart.mk
	build/Android.test.host.mk
	build/Android.test.mk

Change-Id: I84ce2b7a2b4e37799d4d782b97c02d5e97ac081c
diff --git a/Android.mk b/Android.mk
index 4290364..e32cc7a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -27,3 +27,18 @@
     include $(build_path)/Android.test.host.mk
     include $(build_path)/Android.aexec.host.mk
 endif
+
+
+# "m build-art" for quick minimal build
+.PHONY: build-art
+build-art: \
+    $(TARGET_OUT_EXECUTABLES)/aexec \
+    $(foreach file,$(TEST_TARGET_SRC_FILES),$(TARGET_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%))) \
+    $(HOST_OUT_EXECUTABLES)/aexec \
+    $(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%))) \
+#
+
+# "mm test-art-host" to build and run all host tests
+.PHONY: test-art-host
+test-art-host: $(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%)))
+	$(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%)) &&) true
diff --git a/build/Android.aexec.host.mk b/build/Android.aexec.host.mk
index a4d072e..6efc9e9 100644
--- a/build/Android.aexec.host.mk
+++ b/build/Android.aexec.host.mk
@@ -20,7 +20,7 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(build_path)/Android.common.mk
-LOCAL_SRC_FILES := $(AEXEC_LOCAL_SRC_FILES)
+LOCAL_SRC_FILES := $(AEXEC_SRC_FILES)
 
 LOCAL_C_INCLUDES :=
 
diff --git a/build/Android.aexec.mk b/build/Android.aexec.mk
index 2268cbf..411128e 100644
--- a/build/Android.aexec.mk
+++ b/build/Android.aexec.mk
@@ -20,7 +20,7 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(build_path)/Android.common.mk
-LOCAL_SRC_FILES := $(AEXEC_LOCAL_SRC_FILES)
+LOCAL_SRC_FILES := $(AEXEC_SRC_FILES)
 
 include external/stlport/libstlport.mk
 LOCAL_C_INCLUDES +=
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 30a63ca..bf442a3 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -35,10 +35,10 @@
 LOCAL_CFLAGS +=
 endif
 
-AEXEC_LOCAL_SRC_FILES := \
+AEXEC_SRC_FILES := \
 	src/main.cc
 
-LIBART_LOCAL_SRC_FILES := \
+LIBART_COMMON_SRC_FILES := \
 	src/assembler.cc \
 	src/base64.cc \
 	src/class_linker.cc \
@@ -52,28 +52,24 @@
 	src/stringpiece.cc \
 	src/thread.cc
 
-ifeq ($(LIBART_TARGET_ARCH),arm)
-LIBART_LOCAL_SRC_FILES += \
+LIBART_TARGET_SRC_FILES := \
+	$(LIBART_COMMON_SRC_FILES) \
 	src/assembler_arm.cc
-endif
 
-ifeq ($(LIBART_TARGET_ARCH),x86)
-LIBART_LOCAL_SRC_FILES += \
+LIBART_HOST_SRC_FILES := \
+	$(LIBART_COMMON_SRC_FILES) \
 	src/assembler_x86.cc
-endif
 
-TEST_LOCAL_SRC_FILES := \
+TEST_COMMON_SRC_FILES := \
 	src/class_linker_test.cc \
 	src/dex_file_test.cc \
 	src/dex_instruction_visitor_test.cc \
 	src/object_test.cc \
 	src/raw_dex_file_test.cc
 
-ifeq ($(TEST_TARGET_ARCH),arm)
-TEST_LOCAL_SRC_FILES +=
-endif
+TEST_TARGET_SRC_FILES := \
+	$(TEST_COMMON_SRC_FILES)
 
-ifeq ($(TEST_TARGET_ARCH),x86)
-TEST_LOCAL_SRC_FILES += \
+TEST_HOST_SRC_FILES := \
+	$(TEST_COMMON_SRC_FILES) \
 	src/assembler_x86_test.cc
-endif
diff --git a/build/Android.libart.host.mk b/build/Android.libart.host.mk
index cd13677..1612bf8 100644
--- a/build/Android.libart.host.mk
+++ b/build/Android.libart.host.mk
@@ -19,9 +19,8 @@
 LOCAL_MODULE := libart
 LOCAL_MODULE_TAGS := optional
 
-LIBART_TARGET_ARCH := $(HOST_ARCH)
 include $(build_path)/Android.common.mk
-LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES)
+LOCAL_SRC_FILES := $(LIBART_HOST_SRC_FILES)
 
 LOCAL_WHOLE_STATIC_LIBRARIES := \
 	libcutils \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 404f0c6..e9dcfb6 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -19,9 +19,8 @@
 LOCAL_MODULE := libart
 LOCAL_MODULE_TAGS := optional
 
-LIBART_TARGET_ARCH := $(TARGET_ARCH)
 include $(build_path)/Android.common.mk
-LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES)
+LOCAL_SRC_FILES := $(LIBART_TARGET_SRC_FILES)
 
 include external/stlport/libstlport.mk
 
diff --git a/build/Android.test.host.mk b/build/Android.test.host.mk
index 5c32a04..23346d9 100644
--- a/build/Android.test.host.mk
+++ b/build/Android.test.host.mk
@@ -18,7 +18,6 @@
 
 local_module_tags := tests
 
-TEST_TARGET_ARCH := $(HOST_ARCH)
 include $(build_path)/Android.common.mk
 local_cpp_extension := $(LOCAL_CPP_EXTENSION)
 local_cflags := $(LOCAL_CFLAGS)
@@ -33,7 +32,7 @@
 	libgtest_host \
 	libgtest_main_host
 
-$(foreach file,$(TEST_LOCAL_SRC_FILES), \
+$(foreach file,$(TEST_HOST_SRC_FILES), \
   $(eval include $(CLEAR_VARS)) \
   $(eval LOCAL_CPP_EXTENSION := $(local_cpp_extension)) \
   $(eval LOCAL_MODULE := $(notdir $(file:%.cc=%))) \
diff --git a/build/Android.test.mk b/build/Android.test.mk
index fc3917c..7d7b2ce 100644
--- a/build/Android.test.mk
+++ b/build/Android.test.mk
@@ -18,7 +18,6 @@
 
 local_module_tags := tests
 
-TEST_TARGET_ARCH := $(TARGET_ARCH)
 include $(build_path)/Android.common.mk
 local_cpp_extension := $(LOCAL_CPP_EXTENSION)
 local_cflags := $(LOCAL_CFLAGS)
@@ -34,7 +33,7 @@
 	libgtest \
 	libgtest_main
 
-$(foreach file,$(TEST_LOCAL_SRC_FILES), \
+$(foreach file,$(TEST_TARGET_SRC_FILES), \
   $(eval include $(CLEAR_VARS)) \
   $(eval LOCAL_CPP_EXTENSION := $(local_cpp_extension)) \
   $(eval LOCAL_MODULE := $(notdir $(file:%.cc=%))) \
diff --git a/src/class_linker.cc b/src/class_linker.cc
index cf72a11..5b50113 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -20,10 +20,11 @@
 namespace art {
 
 void ClassLinker::Init() {
-  // Allocate and partially initialize the class Class.  This object
-  // will complete its initialization when its definition is loaded.
-  java_lang_Class_ = Heap::AllocClass();
-  java_lang_Class_->super_class_ = java_lang_Class_;
+  // Allocate and partially initialize the Object and Class classes.
+  // Initialization will be completed when the definitions are loaded.
+  java_lang_Object_ = Heap::AllocClass(NULL);
+  java_lang_Object_->descriptor_ = "Ljava/lang/Object;";
+  java_lang_Class_ = Heap::AllocClass(NULL);
   java_lang_Class_->descriptor_ = "Ljava/lang/Class;";
 
   // Allocate and initialize the primitive type classes.
@@ -56,12 +57,16 @@
       }
     }
     // Load the class from the dex file.
-    if (!strcmp(descriptor, "Ljava/lang/Class;")) {
+    if (!strcmp(descriptor, "Ljava/lang/Object;")) {
+      klass = java_lang_Object_;
+      klass->dex_file_ = dex_file;
+    } else if (!strcmp(descriptor, "Ljava/lang/Class;")) {
       klass = java_lang_Class_;
+      klass->dex_file_ = dex_file;
     } else {
-      klass = Heap::AllocClass();
+      klass = Heap::AllocClass(dex_file);
     }
-    bool is_loaded = dex_file->LoadClass(descriptor, klass);
+    bool is_loaded = LoadClass(descriptor, klass);
     if (!is_loaded) {
       // TODO: this occurs only when a dex file is provided.
       LG << "Class not found";  // TODO: NoClassDefFoundError
@@ -116,6 +121,153 @@
   return klass;
 }
 
+bool ClassLinker::LoadClass(const char* descriptor, Class* klass) {
+  const RawDexFile* raw = klass->GetDexFile()->GetRaw();
+  const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor);
+  if (class_def == NULL) {
+    return false;
+  } else {
+    return LoadClass(*class_def, klass);
+  }
+}
+
+bool ClassLinker::LoadClass(const RawDexFile::ClassDef& class_def, Class* klass) {
+  CHECK(klass != NULL);
+  CHECK(klass->dex_file_ != NULL);
+  const RawDexFile* raw = klass->GetDexFile()->GetRaw();
+  const byte* class_data = raw->GetClassData(class_def);
+  RawDexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data);
+
+  const char* descriptor = raw->GetClassDescriptor(class_def);
+  CHECK(descriptor != NULL);
+
+  klass->klass_ = java_lang_Class_;
+  klass->descriptor_.set(descriptor);
+  klass->descriptor_alloc_ = NULL;
+  klass->access_flags_ = class_def.access_flags_;
+  klass->class_loader_ = NULL;  // TODO
+  klass->primitive_type_ = Class::kPrimNot;
+  klass->status_ = Class::kStatusIdx;
+
+  klass->super_class_ = NULL;
+  klass->super_class_idx_ = class_def.superclass_idx_;
+
+  klass->num_sfields_ = header.static_fields_size_;
+  klass->num_ifields_ = header.instance_fields_size_;
+  klass->num_direct_methods_ = header.direct_methods_size_;
+  klass->num_virtual_methods_ = header.virtual_methods_size_;
+
+  klass->source_file_ = raw->dexGetSourceFile(class_def);
+
+  // Load class interfaces.
+  LoadInterfaces(class_def, klass);
+
+  // Load static fields.
+  if (klass->num_sfields_ != 0) {
+    // TODO: allocate on the object heap.
+    klass->sfields_ = new StaticField[klass->NumStaticFields()]();
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->num_sfields_; ++i) {
+      RawDexFile::Field raw_field;
+      raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
+      LoadField(klass, raw_field, &klass->sfields_[i]);
+    }
+  }
+
+  // Load instance fields.
+  if (klass->NumInstanceFields() != 0) {
+    // TODO: allocate on the object heap.
+    klass->ifields_ = new InstanceField[klass->NumInstanceFields()]();
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
+      RawDexFile::Field raw_field;
+      raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
+      LoadField(klass, raw_field, klass->GetInstanceField(i));
+    }
+  }
+
+  // Load direct methods.
+  if (klass->NumDirectMethods() != 0) {
+    // TODO: append direct methods to class object
+    klass->direct_methods_ = new Method[klass->NumDirectMethods()]();
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
+      RawDexFile::Method raw_method;
+      raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
+      LoadMethod(klass, raw_method, klass->GetDirectMethod(i));
+      // TODO: register maps
+    }
+  }
+
+  // Load virtual methods.
+  if (klass->NumVirtualMethods() != 0) {
+    // TODO: append virtual methods to class object
+    klass->virtual_methods_ = new Method[klass->NumVirtualMethods()]();
+    uint32_t last_idx = 0;
+    for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+      RawDexFile::Method raw_method;
+      raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
+      LoadMethod(klass, raw_method, klass->GetVirtualMethod(i));
+      // TODO: register maps
+    }
+  }
+
+  return klass;
+}
+
+void ClassLinker::LoadInterfaces(const RawDexFile::ClassDef& class_def,
+                                 Class* klass) {
+  const RawDexFile* raw = klass->GetDexFile()->GetRaw();
+  const RawDexFile::TypeList* list = raw->GetInterfacesList(class_def);
+  if (list != NULL) {
+    klass->interface_count_ = list->Size();
+    // TODO: allocate the interfaces array on the object heap.
+    klass->interfaces_ = new Class*[list->Size()]();
+    for (size_t i = 0; i < list->Size(); ++i) {
+      const RawDexFile::TypeItem& type_item = list->GetTypeItem(i);
+      klass->interfaces_[i] = reinterpret_cast<Class*>(type_item.type_idx_);
+    }
+  }
+}
+
+void ClassLinker::LoadField(Class* klass, const RawDexFile::Field& src,
+                            Field* dst) {
+  const RawDexFile* raw = klass->GetDexFile()->GetRaw();
+  const RawDexFile::FieldId& field_id = raw->GetFieldId(src.field_idx_);
+  dst->klass_ = klass;
+  dst->name_ = raw->dexStringById(field_id.name_idx_);
+  dst->signature_ = raw->dexStringByTypeIdx(field_id.type_idx_);
+  dst->access_flags_ = src.access_flags_;
+}
+
+void ClassLinker::LoadMethod(Class* klass, const RawDexFile::Method& src,
+                             Method* dst) {
+  const RawDexFile* raw = klass->GetDexFile()->GetRaw();
+  const RawDexFile::MethodId& method_id = raw->GetMethodId(src.method_idx_);
+  dst->klass_ = klass;
+  dst->name_.set(raw->dexStringById(method_id.name_idx_));
+  dst->proto_idx_ = method_id.proto_idx_;
+  dst->shorty_.set(raw->GetShorty(method_id.proto_idx_));
+  dst->access_flags_ = src.access_flags_;
+
+  // TODO: check for finalize method
+
+  const RawDexFile::CodeItem* code_item = raw->GetCodeItem(src);
+  if (code_item != NULL) {
+    dst->num_registers_ = code_item->registers_size_;
+    dst->num_ins_ = code_item->ins_size_;
+    dst->num_outs_ = code_item->outs_size_;
+    dst->insns_ = code_item->insns_;
+  } else {
+    uint16_t num_args = dst->NumArgRegisters();
+    if (!dst->IsStatic()) {
+      ++num_args;
+    }
+    dst->num_registers_ = dst->num_ins_ + num_args;
+    // TODO: native methods
+  }
+}
+
 DexFile* ClassLinker::FindInClassPath(const char* descriptor) {
   for (size_t i = 0; i != class_path_.size(); ++i) {
     DexFile* dex_file = class_path_[i];
@@ -131,7 +283,7 @@
 }
 
 Class* ClassLinker::CreatePrimitiveClass(JType type, const char* descriptor) {
-  Class* klass = Heap::AllocClass();
+  Class* klass = Heap::AllocClass(NULL);
   CHECK(klass != NULL);
   klass->super_class_ = java_lang_Class_;
   klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
@@ -348,8 +500,8 @@
 }
 
 bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
-                                                const Class* klass1,
-                                                const Class* klass2) {
+                                                 const Class* klass1,
+                                                 const Class* klass2) {
   const RawDexFile* raw = method->GetClass()->GetDexFile()->GetRaw();
   const RawDexFile::ProtoId& proto_id = raw->GetProtoId(method->proto_idx_);
   RawDexFile::ParameterIterator *it;
@@ -378,8 +530,8 @@
 // Returns true if classes referenced by the descriptor are the
 // same classes in klass1 as they are in klass2.
 bool ClassLinker::HasSameDescriptorClasses(const char* descriptor,
-                                          const Class* klass1,
-                                          const Class* klass2) {
+                                           const Class* klass1,
+                                           const Class* klass2) {
   CHECK(descriptor != NULL);
   CHECK(klass1 != NULL);
   CHECK(klass2 != NULL);
@@ -432,7 +584,7 @@
     return;
   }
   const char* descriptor = klass->GetDescriptor().data();
-  RawDexFile* raw = dex_file->GetRaw();
+  const RawDexFile* raw = dex_file->GetRaw();
   const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor);
   CHECK(class_def != NULL);
   const byte* addr = raw->GetEncodedArray(*class_def);
diff --git a/src/class_linker.h b/src/class_linker.h
index 89fd8f7..3796dc2 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -30,6 +30,10 @@
     return FindClass(descriptor, NULL, NULL);
   }
 
+  bool LoadClass(const char* descriptor, Class* klass);
+
+  bool LoadClass(const RawDexFile::ClassDef& class_def, Class* klass);
+
   Class* FindPrimitiveClass(JType type);
 
   bool InitializeClass(Class* klass);
@@ -47,6 +51,12 @@
  private:
   Class* CreatePrimitiveClass(JType type, const char* descriptor);
 
+  void LoadInterfaces(const RawDexFile::ClassDef& class_def, Class *klass);
+
+  void LoadField(Class* klass, const RawDexFile::Field& src, Field* dst);
+
+  void LoadMethod(Class* klass, const RawDexFile::Method& src, Method* dst);
+
   // Inserts a class into the class table.  Returns true if the class
   // was inserted.
   bool InsertClass(Class* klass);
@@ -104,6 +114,7 @@
   Class* primitive_long_;
   Class* primitive_void_;
 
+  Class* java_lang_Object_;
   Class* java_lang_Class_;
 
   DISALLOW_COPY_AND_ASSIGN(ClassLinker);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 7bb9ecb..5cd8a6f 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -1,31 +1,95 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 
+#include "src/common_test.h"
 #include "src/class_linker.h"
 #include "src/dex_file.h"
+#include "src/heap.h"
 #include "gtest/gtest.h"
 
 namespace art {
 
-static const char kMyClassDex[] =
-"ZGV4CjAzNQDyNgSqujckc8oAvOKGLvz3+wrLfW9ED5AIAgAAcAAAAHhWNBIAAAAAAAAAAIABAAAG"
-"AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAIAAACgAAAAAgAAALAAAAAYAQAA8AAAABwB"
-"AAAkAQAALwEAAEMBAABRAQAAXgEAAAEAAAACAAAABQAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAQAA"
-"AAAAAAABAAAAAQAAAP////8AAAAABAAAAAAAAABrAQAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAA"
-"AAAAAHUBAAAAAAAAAQABAAAAAABhAQAAAQAAAA4AAAABAAEAAQAAAGYBAAAEAAAAcBABAAAADgAG"
-"PGluaXQ+AAlMTXlDbGFzczsAEkxqYXZhL2xhbmcvT2JqZWN0OwAMTXlDbGFzcy5qYXZhAAtPYmpl"
-"Y3QuamF2YQABVgADAAcOAAEABw4AAAABAAGBgATwAQAAAQAAgIAEhAIACwAAAAAAAAABAAAAAAAA"
-"AAEAAAAGAAAAcAAAAAIAAAADAAAAiAAAAAMAAAABAAAAlAAAAAUAAAACAAAAoAAAAAYAAAACAAAA"
-"sAAAAAEgAAACAAAA8AAAAAIgAAAGAAAAHAEAAAMgAAACAAAAYQEAAAAgAAACAAAAawEAAAAQAAAB"
-"AAAAgAEAAA==";
+TEST(ClassLinker, LoadNonexistent) {
+  scoped_ptr<DexFile> dex(DexFile::OpenBase64(kMyClassDex));
+  ASSERT_TRUE(dex != NULL);
+
+  ClassLinker linker;
+  linker.Init();
+  linker.AppendToClassPath(dex.get());
+
+  scoped_ptr<Class> klass(Heap::AllocClass(dex.get()));
+  bool result1 = linker.LoadClass("NoSuchClass", klass.get());
+  EXPECT_FALSE(result1);
+  bool result2 = linker.LoadClass("LNoSuchClass;", klass.get());
+  EXPECT_FALSE(result2);
+}
+
+TEST(ClassLinker, Load) {
+  scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex));
+  ASSERT_TRUE(dex != NULL);
+
+  ClassLinker linker;
+  linker.Init();
+  linker.AppendToClassPath(dex.get());
+
+  scoped_ptr<Class> klass(Heap::AllocClass(dex.get()));
+  bool result = linker.LoadClass("LNested;", klass.get());
+  ASSERT_TRUE(result);
+
+  uint32_t vmeth = klass->NumVirtualMethods();
+  EXPECT_EQ(vmeth, 0U);
+
+  uint32_t dmeth = klass->NumDirectMethods();
+  EXPECT_EQ(dmeth, 1U);
+}
 
 TEST(ClassLinker, FindClass) {
   scoped_ptr<DexFile> dex(DexFile::OpenBase64(kMyClassDex));
   ASSERT_TRUE(dex != NULL);
 
   ClassLinker linker;
+  linker.Init();
   linker.AppendToClassPath(dex.get());
-  Class* klass = linker.FindClass("LMyClass;", NULL, dex.get());
-  EXPECT_TRUE(klass != NULL);
+
+  Class* JavaLangObject = linker.FindClass("Ljava/lang/Object;", NULL, dex.get());
+  ASSERT_TRUE(JavaLangObject != NULL);
+  EXPECT_TRUE(JavaLangObject->GetClass() != NULL);
+  ASSERT_TRUE(JavaLangObject->GetDescriptor() == "Ljava/lang/Object;");
+  EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
+  EXPECT_FALSE(JavaLangObject->HasSuperClass());
+  EXPECT_TRUE(JavaLangObject->GetComponentType() == NULL);
+  EXPECT_FALSE(JavaLangObject->IsErroneous());
+  EXPECT_FALSE(JavaLangObject->IsVerified());
+  EXPECT_TRUE(JavaLangObject->IsLinked());
+  EXPECT_FALSE(JavaLangObject->IsArray());
+  EXPECT_FALSE(JavaLangObject->IsInterface());
+  EXPECT_TRUE(JavaLangObject->IsPublic());
+  EXPECT_FALSE(JavaLangObject->IsFinal());
+  EXPECT_FALSE(JavaLangObject->IsPrimitive());
+  EXPECT_EQ((size_t) 1, JavaLangObject->NumDirectMethods());
+  EXPECT_EQ((size_t) 0, JavaLangObject->NumVirtualMethods());
+  EXPECT_EQ((size_t) 0, JavaLangObject->NumInstanceFields());
+  EXPECT_EQ((size_t) 0, JavaLangObject->NumStaticFields());
+
+  Class* MyClass = linker.FindClass("LMyClass;", NULL, dex.get());
+  ASSERT_TRUE(MyClass != NULL);
+  EXPECT_TRUE(MyClass->GetClass() != NULL);
+  ASSERT_TRUE(MyClass->GetDescriptor() == "LMyClass;");
+  EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
+  EXPECT_TRUE(MyClass->HasSuperClass());
+  EXPECT_TRUE(MyClass->GetComponentType() == NULL);
+  EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
+  EXPECT_FALSE(MyClass->IsErroneous());
+  EXPECT_FALSE(MyClass->IsVerified());
+  EXPECT_TRUE(MyClass->IsLinked());
+  EXPECT_FALSE(MyClass->IsArray());
+  EXPECT_FALSE(MyClass->IsInterface());
+  EXPECT_FALSE(MyClass->IsPublic());
+  EXPECT_FALSE(MyClass->IsFinal());
+  EXPECT_FALSE(MyClass->IsPrimitive());
+  EXPECT_EQ((size_t) 1, MyClass->NumDirectMethods());
+  EXPECT_EQ((size_t) 0, MyClass->NumVirtualMethods());
+  EXPECT_EQ((size_t) 0, MyClass->NumInstanceFields());
+  EXPECT_EQ((size_t) 0, MyClass->NumStaticFields());
 }
 
 }  // namespace art
diff --git a/src/common_test.h b/src/common_test.h
new file mode 100644
index 0000000..9747261
--- /dev/null
+++ b/src/common_test.h
@@ -0,0 +1,89 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+namespace art {
+
+// package java.lang;
+// public class Object {}
+//
+// class MyClass {}
+static const char kMyClassDex[] =
+  "ZGV4CjAzNQA5Nm9IrCVm91COwepff7LhIE23GZIxGjgIAgAAcAAAAHhWNBIAAAAAAAAAAIABAAAG"
+  "AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAIAAACgAAAAAgAAALAAAAAYAQAA8AAAABwB"
+  "AAAkAQAALwEAAEMBAABRAQAAXgEAAAEAAAACAAAABQAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAQAA"
+  "AAAAAAABAAAAAQAAAP////8AAAAABAAAAAAAAABrAQAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAA"
+  "AAAAAHUBAAAAAAAAAQABAAAAAABhAQAAAQAAAA4AAAABAAEAAQAAAGYBAAAEAAAAcBABAAAADgAG"
+  "PGluaXQ+AAlMTXlDbGFzczsAEkxqYXZhL2xhbmcvT2JqZWN0OwAMTXlDbGFzcy5qYXZhAAtPYmpl"
+  "Y3QuamF2YQABVgACAAcOAAUABw4AAAABAAGBgATwAQAAAQAAgIAEhAIACwAAAAAAAAABAAAAAAAA"
+  "AAEAAAAGAAAAcAAAAAIAAAADAAAAiAAAAAMAAAABAAAAlAAAAAUAAAACAAAAoAAAAAYAAAACAAAA"
+  "sAAAAAEgAAACAAAA8AAAAAIgAAAGAAAAHAEAAAMgAAACAAAAYQEAAAAgAAACAAAAawEAAAAQAAAB"
+  "AAAAgAEAAA==";
+
+// class Nested {
+//     class Inner {
+//     }
+// }
+static const char kNestedDex[] =
+  "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP"
+  "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B"
+  "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA"
+  "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA"
+  "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA"
+  "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA"
+  "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA"
+  "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu"
+  "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2"
+  "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz"
+  "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA"
+  "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA"
+  "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH"
+  "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ"
+  "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA"
+  "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA==";
+
+// class ProtoCompare {
+//     int m1(short x, int y, long z) { return x + y + (int)z; }
+//     int m2(short x, int y, long z) { return x + y + (int)z; }
+//     int m3(long x, int y, short z) { return (int)x + y + z; }
+//     long m4(long x, int y, short z) { return x + y + z; }
+// }
+static const char kProtoCompareDex[] =
+  "ZGV4CjAzNQBLUetu+TVZ8gsYsCOFoij7ecsHaGSEGA8gAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP"
+  "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B"
+  "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAOAgAAIgIAADUCAAA4AgAAOwIAAD8CAABDAgAARwIA"
+  "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA"
+  "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD"
+  "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHACAAAAAAAAAQABAAEAAABLAgAABAAAAHAQ"
+  "BQAAAA4ABwAFAAAAAABQAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWAIAAAUAAACQAAMEhFGw"
+  "EA8AAAAGAAUAAAAAAGACAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGgCAAAFAAAAgXC7UIGCuyAQAAAA"
+  "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMADkxQ"
+  "cm90b0NvbXBhcmU7ABJMamF2YS9sYW5nL09iamVjdDsAEVByb3RvQ29tcGFyZS5qYXZhAAFTAAFW"
+  "AAJtMQACbTIAAm0zAAJtNAABAAcOAAIDAAAABw4AAwMAAAAHDgAEAwAAAAcOAAUDAAAABw4AAAAB"
+  "BACAgATEAgEA3AIBAPgCAQCUAwEArAMAAAwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA"
+  "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB"
+  "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAEsCAAAAIAAAAQAAAHACAAAAEAAAAQAAAIwC"
+  "AAA=";
+
+// class ProtoCompare2 {
+//     int m1(short x, int y, long z) { return x + y + (int)z; }
+//     int m2(short x, int y, long z) { return x + y + (int)z; }
+//     int m3(long x, int y, short z) { return (int)x + y + z; }
+//     long m4(long x, int y, short z) { return x + y + z; }
+// }
+static const char kProtoCompare2Dex[] =
+  "ZGV4CjAzNQDVUXj687EpyTTDJZEZPA8dEYnDlm0Ir6YgAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP"
+  "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B"
+  "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAPAgAAIwIAADcCAAA6AgAAPQIAAEECAABFAgAASQIA"
+  "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA"
+  "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD"
+  "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHICAAAAAAAAAQABAAEAAABNAgAABAAAAHAQ"
+  "BQAAAA4ABwAFAAAAAABSAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWgIAAAUAAACQAAMEhFGw"
+  "EA8AAAAGAAUAAAAAAGICAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGoCAAAFAAAAgXC7UIGCuyAQAAAA"
+  "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMAD0xQ"
+  "cm90b0NvbXBhcmUyOwASTGphdmEvbGFuZy9PYmplY3Q7ABJQcm90b0NvbXBhcmUyLmphdmEAAVMA"
+  "AVYAAm0xAAJtMgACbTMAAm00AAEABw4AAgMAAAAHDgADAwAAAAcOAAQDAAAABw4ABQMAAAAHDgAA"
+  "AAEEAICABMQCAQDcAgEA+AIBAJQDAQCsAwwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA"
+  "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB"
+  "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAE0CAAAAIAAAAQAAAHICAAAAEAAAAQAAAIwC"
+  "AAA=";
+
+}  // namespace art
diff --git a/src/dex_file.cc b/src/dex_file.cc
index c9604a1..5b39bfc 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -49,147 +49,4 @@
   fields_ = new Field*[num_fields_]();
 }
 
-bool DexFile::LoadClass(const char* descriptor, Class* klass) {
-  const RawDexFile::ClassDef* class_def = raw_->FindClassDef(descriptor);
-  if (class_def == NULL) {
-    return false;
-  } else {
-    return LoadClass(*class_def, klass);
-  }
-}
-
-bool DexFile::LoadClass(const RawDexFile::ClassDef& class_def, Class* klass) {
-  CHECK(klass != NULL);
-  const byte* class_data = raw_->GetClassData(class_def);
-  RawDexFile::ClassDataHeader header = raw_->ReadClassDataHeader(&class_data);
-
-  const char* descriptor = raw_->GetClassDescriptor(class_def);
-  CHECK(descriptor != NULL);
-
-  klass->klass_ = NULL;  // TODO
-  klass->descriptor_.set(descriptor);
-  klass->descriptor_alloc_ = NULL;
-  klass->access_flags_ = class_def.access_flags_;
-  klass->class_loader_ = NULL;  // TODO
-  klass->dex_file_ = this;
-  klass->primitive_type_ = Class::kPrimNot;
-  klass->status_ = Class::kStatusIdx;
-
-  klass->super_class_ = NULL;
-  klass->super_class_idx_ = class_def.superclass_idx_;
-
-  klass->num_sfields_ = header.static_fields_size_;
-  klass->num_ifields_ = header.instance_fields_size_;
-  klass->num_direct_methods_ = header.direct_methods_size_;
-  klass->num_virtual_methods_ = header.virtual_methods_size_;
-
-  klass->source_file_ = raw_->dexGetSourceFile(class_def);
-
-  // Load class interfaces.
-  LoadInterfaces(class_def, klass);
-
-  // Load static fields.
-  if (klass->num_sfields_ != 0) {
-    // TODO: allocate on the object heap.
-    klass->sfields_ = new StaticField[klass->NumStaticFields()]();
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < klass->num_sfields_; ++i) {
-      RawDexFile::Field raw_field;
-      raw_->dexReadClassDataField(&class_data, &raw_field, &last_idx);
-      LoadField(klass, raw_field, &klass->sfields_[i]);
-    }
-  }
-
-  // Load instance fields.
-  if (klass->NumInstanceFields() != 0) {
-    // TODO: allocate on the object heap.
-    klass->ifields_ = new InstanceField[klass->NumInstanceFields()]();
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
-      RawDexFile::Field raw_field;
-      raw_->dexReadClassDataField(&class_data, &raw_field, &last_idx);
-      LoadField(klass, raw_field, klass->GetInstanceField(i));
-    }
-  }
-
-  // Load direct methods.
-  if (klass->NumDirectMethods() != 0) {
-    // TODO: append direct methods to class object
-    klass->direct_methods_ = new Method[klass->NumDirectMethods()]();
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
-      RawDexFile::Method raw_method;
-      raw_->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
-      LoadMethod(klass, raw_method, klass->GetDirectMethod(i));
-      // TODO: register maps
-    }
-  }
-
-  // Load virtual methods.
-  if (klass->NumVirtualMethods() != 0) {
-    // TODO: append virtual methods to class object
-    klass->virtual_methods_ = new Method[klass->NumVirtualMethods()]();
-    uint32_t last_idx = 0;
-    for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
-      RawDexFile::Method raw_method;
-      raw_->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
-      LoadMethod(klass, raw_method, klass->GetVirtualMethod(i));
-      // TODO: register maps
-    }
-  }
-
-  return klass;
-}
-
-void DexFile::LoadInterfaces(const RawDexFile::ClassDef& class_def,
-                             Class* klass) {
-  const RawDexFile::TypeList* list = raw_->GetInterfacesList(class_def);
-  if (list != NULL) {
-    klass->interface_count_ = list->Size();
-    // TODO: allocate the interfaces array on the object heap.
-    klass->interfaces_ = new Class*[list->Size()]();
-    for (size_t i = 0; i < list->Size(); ++i) {
-      const RawDexFile::TypeItem& type_item = list->GetTypeItem(i);
-      klass->interfaces_[i] = reinterpret_cast<Class*>(type_item.type_idx_);
-    }
-  }
-}
-
-void DexFile::LoadField(Class* klass, const RawDexFile::Field& src,
-                        Field* dst) {
-  const RawDexFile::FieldId& field_id = raw_->GetFieldId(src.field_idx_);
-  dst->klass_ = klass;
-  dst->name_ = raw_->dexStringById(field_id.name_idx_);
-  dst->signature_ = raw_->dexStringByTypeIdx(field_id.type_idx_);
-  dst->access_flags_ = src.access_flags_;
-}
-
-void DexFile::LoadMethod(Class* klass, const RawDexFile::Method& src,
-                         Method* dst) {
-  const RawDexFile::MethodId& method_id = raw_->GetMethodId(src.method_idx_);
-  dst->klass_ = klass;
-  dst->name_.set(raw_->dexStringById(method_id.name_idx_));
-  dst->dex_file_ = this;
-  dst->proto_idx_ = method_id.proto_idx_;
-  dst->shorty_.set(raw_->GetShorty(method_id.proto_idx_));
-  dst->access_flags_ = src.access_flags_;
-
-  // TODO: check for finalize method
-
-  const RawDexFile::CodeItem* code_item = raw_->GetCodeItem(src);
-  if (code_item != NULL) {
-    dst->num_registers_ = code_item->registers_size_;
-    dst->num_ins_ = code_item->ins_size_;
-    dst->num_outs_ = code_item->outs_size_;
-    dst->insns_ = code_item->insns_;
-  } else {
-    uint16_t num_args = dst->NumArgRegisters();
-    if (!dst->IsStatic()) {
-      ++num_args;
-    }
-    dst->num_registers_ = dst->num_ins_ + num_args;
-    // TODO: native methods
-  }
-}
-
 }  // namespace art
diff --git a/src/dex_file.h b/src/dex_file.h
index 8463672..d11b3b5 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -40,10 +40,6 @@
     return num_methods_;
   }
 
-  bool LoadClass(const char* descriptor, Class* klass);
-
-  bool LoadClass(const RawDexFile::ClassDef& class_def, Class* klass);
-
   bool HasClass(const char* descriptor) {
     return raw_->FindClassDef(descriptor) != NULL;
   }
@@ -77,12 +73,6 @@
 
   void Init();
 
-  void LoadInterfaces(const RawDexFile::ClassDef& class_def, Class *klass);
-
-  void LoadField(Class* klass, const RawDexFile::Field& src, Field* dst);
-
-  void LoadMethod(Class* klass, const RawDexFile::Method& src, Method* dst);
-
   // Table of contents for interned String objects.
   String** strings_;
   size_t num_strings_;
diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc
index ccac396..e12f8e2 100644
--- a/src/dex_file_test.cc
+++ b/src/dex_file_test.cc
@@ -1,5 +1,6 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 
+#include "src/common_test.h"
 #include "src/dex_file.h"
 #include "src/object.h"
 #include "src/scoped_ptr.h"
@@ -9,55 +10,9 @@
 
 namespace art {
 
-// class Nested {
-//     class Inner {
-//     }
-// }
-static const char kNestedDex[] =
-  "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP"
-  "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B"
-  "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA"
-  "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA"
-  "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA"
-  "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA"
-  "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA"
-  "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu"
-  "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2"
-  "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz"
-  "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA"
-  "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA"
-  "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH"
-  "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ"
-  "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA"
-  "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA==";
-
 TEST(DexFile, Open) {
   scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex));
   ASSERT_TRUE(dex != NULL);
 }
 
-TEST(DexFile, LoadNonexistent) {
-  scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex));
-  ASSERT_TRUE(dex != NULL);
-
-  scoped_ptr<Class> klass(reinterpret_cast<Class*>(new byte[sizeof(Class)]));
-  bool result = dex->LoadClass("NoSuchClass", klass.get());
-  ASSERT_FALSE(result);
-}
-
-TEST(DexFile, Load) {
-  scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex));
-  ASSERT_TRUE(dex != NULL);
-
-  scoped_ptr<Class> klass(reinterpret_cast<Class*>(new byte[sizeof(Class)]));
-  bool result = dex->LoadClass("LNested;", klass.get());
-  ASSERT_TRUE(result);
-
-  uint32_t vmeth = klass->NumVirtualMethods();
-  EXPECT_EQ(vmeth, 0U);
-
-  uint32_t dmeth = klass->NumDirectMethods();
-  EXPECT_EQ(dmeth, 1U);
-}
-
 }  // namespace art
diff --git a/src/heap.h b/src/heap.h
index d6b1649..7b31ebc 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -11,9 +11,11 @@
 
 class Heap {
  public:
-  static Class* AllocClass() {
+  static Class* AllocClass(DexFile* dex_file) {
     byte* raw = new byte[sizeof(Class)]();
-    return reinterpret_cast<Class*>(raw);
+    Class* klass = reinterpret_cast<Class*>(raw);
+    klass->dex_file_ = dex_file;
+    return klass;
   }
 
   static CharArray* AllocCharArray(size_t length) {
diff --git a/src/object.cc b/src/object.cc
index 7c28d76..d897c52 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -69,9 +69,9 @@
 }
 
 bool Method::HasSameArgumentTypes(const Method* that) const {
-  const RawDexFile* raw1 = this->dex_file_->GetRaw();
+  const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw();
   const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_);
-  const RawDexFile* raw2 = that->dex_file_->GetRaw();
+  const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw();
   const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_);
 
   // TODO: compare ProtoId objects for equality and exit early
@@ -101,11 +101,11 @@
 }
 
 bool Method::HasSameReturnType(const Method* that) const {
-  const RawDexFile* raw1 = this->dex_file_->GetRaw();
+  const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw();
   const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_);
   const char* type1 = raw1->dexStringByTypeIdx(proto1.return_type_idx_);
 
-  const RawDexFile* raw2 = that->dex_file_->GetRaw();
+  const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw();
   const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_);
   const char* type2 = raw2->dexStringByTypeIdx(proto2.return_type_idx_);
 
diff --git a/src/object.h b/src/object.h
index 2b75ff7..3bad627 100644
--- a/src/object.h
+++ b/src/object.h
@@ -311,7 +311,7 @@
   }
 
   // const char* GetReturnTypeDescriptor() const {
-  //   return dex_file_->GetRaw()->dexStringByTypeIdx(proto_id_.return_type_id_);
+  //   return klass_->GetDexFile_->GetRaw()->dexStringByTypeIdx(proto_id_.return_type_id_);
   // }
 
   // Returns true if the method is declared public.
@@ -398,10 +398,6 @@
   // method name, e.g. "<init>" or "eatLunch"
   StringPiece name_;
 
-  // A pointer to the DEX file this class was loaded from or NULL for
-  // proxy objects.
-  DexFile* dex_file_;
-
   // Method prototype descriptor string (return and argument types).
   uint32_t proto_idx_;
 
diff --git a/src/object_test.cc b/src/object_test.cc
index 6ce3570..49dda32 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -1,7 +1,10 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 // Author: cshapiro@google.com (Carl Shapiro)
 
+#include "src/class_linker.h"
+#include "src/common_test.h"
 #include "src/dex_file.h"
+#include "src/heap.h"
 #include "src/object.h"
 #include "src/scoped_ptr.h"
 
@@ -24,37 +27,18 @@
                                       "Ljava/lang/reflect/Method;"));
 }
 
-// class ProtoCompare {
-//     int m1(short x, int y, long z) { return x + y + (int)z; }
-//     int m2(short x, int y, long z) { return x + y + (int)z; }
-//     int m3(long x, int y, short z) { return (int)x + y + z; }
-//     long m4(long x, int y, short z) { return x + y + z; }
-// }
-static const char kProtoCompareDex[] =
-  "ZGV4CjAzNQBLUetu+TVZ8gsYsCOFoij7ecsHaGSEGA8gAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP"
-  "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B"
-  "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAOAgAAIgIAADUCAAA4AgAAOwIAAD8CAABDAgAARwIA"
-  "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA"
-  "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD"
-  "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHACAAAAAAAAAQABAAEAAABLAgAABAAAAHAQ"
-  "BQAAAA4ABwAFAAAAAABQAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWAIAAAUAAACQAAMEhFGw"
-  "EA8AAAAGAAUAAAAAAGACAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGgCAAAFAAAAgXC7UIGCuyAQAAAA"
-  "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMADkxQ"
-  "cm90b0NvbXBhcmU7ABJMamF2YS9sYW5nL09iamVjdDsAEVByb3RvQ29tcGFyZS5qYXZhAAFTAAFW"
-  "AAJtMQACbTIAAm0zAAJtNAABAAcOAAIDAAAABw4AAwMAAAAHDgAEAwAAAAcOAAUDAAAABw4AAAAB"
-  "BACAgATEAgEA3AIBAPgCAQCUAwEArAMAAAwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA"
-  "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB"
-  "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAEsCAAAAIAAAAQAAAHACAAAAEAAAAQAAAIwC"
-  "AAA=";
-
 // TODO: test 0 argument methods
 // TODO: make this test simpler and shorter
 TEST(Method, ProtoCompare) {
   scoped_ptr<DexFile> dex_file(DexFile::OpenBase64(kProtoCompareDex));
   ASSERT_TRUE(dex_file != NULL);
 
-  scoped_ptr<Class> klass(reinterpret_cast<Class*>(new byte[sizeof(Class)]));
-  bool result = dex_file->LoadClass("LProtoCompare;", klass.get());
+  ClassLinker linker;
+  linker.Init();
+  linker.AppendToClassPath(dex_file.get());
+
+  scoped_ptr<Class> klass(Heap::AllocClass(dex_file.get()));
+  bool result = linker.LoadClass("LProtoCompare;", klass.get());
   ASSERT_TRUE(result);
 
   ASSERT_EQ(4U, klass->NumVirtualMethods());
@@ -102,40 +86,23 @@
   EXPECT_FALSE(m1->HasSameNameAndPrototype(m2));
 }
 
-// class ProtoCompare2 {
-//     int m1(short x, int y, long z) { return x + y + (int)z; }
-//     int m2(short x, int y, long z) { return x + y + (int)z; }
-//     int m3(long x, int y, short z) { return (int)x + y + z; }
-//     long m4(long x, int y, short z) { return x + y + z; }
-// }
-static const char kProtoCompare2Dex[] =
-  "ZGV4CjAzNQDVUXj687EpyTTDJZEZPA8dEYnDlm0Ir6YgAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP"
-  "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B"
-  "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAPAgAAIwIAADcCAAA6AgAAPQIAAEECAABFAgAASQIA"
-  "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA"
-  "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD"
-  "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHICAAAAAAAAAQABAAEAAABNAgAABAAAAHAQ"
-  "BQAAAA4ABwAFAAAAAABSAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWgIAAAUAAACQAAMEhFGw"
-  "EA8AAAAGAAUAAAAAAGICAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGoCAAAFAAAAgXC7UIGCuyAQAAAA"
-  "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMAD0xQ"
-  "cm90b0NvbXBhcmUyOwASTGphdmEvbGFuZy9PYmplY3Q7ABJQcm90b0NvbXBhcmUyLmphdmEAAVMA"
-  "AVYAAm0xAAJtMgACbTMAAm00AAEABw4AAgMAAAAHDgADAwAAAAcOAAQDAAAABw4ABQMAAAAHDgAA"
-  "AAEEAICABMQCAQDcAgEA+AIBAJQDAQCsAwwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA"
-  "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB"
-  "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAE0CAAAAIAAAAQAAAHICAAAAEAAAAQAAAIwC"
-  "AAA=";
-
 TEST(Method, ProtoCompare2) {
   scoped_ptr<DexFile> dex_file1(DexFile::OpenBase64(kProtoCompareDex));
   ASSERT_TRUE(dex_file1 != NULL);
   scoped_ptr<DexFile> dex_file2(DexFile::OpenBase64(kProtoCompare2Dex));
   ASSERT_TRUE(dex_file2 != NULL);
+  ClassLinker linker1;
+  linker1.Init();
+  linker1.AppendToClassPath(dex_file1.get());
+  ClassLinker linker2;
+  linker2.Init();
+  linker2.AppendToClassPath(dex_file2.get());
 
-  scoped_ptr<Class> klass1(reinterpret_cast<Class*>(new byte[sizeof(Class)]));
-  bool result1 = dex_file1->LoadClass("LProtoCompare;", klass1.get());
+  scoped_ptr<Class> klass1(Heap::AllocClass(dex_file1.get()));
+  bool result1 = linker1.LoadClass("LProtoCompare;", klass1.get());
   ASSERT_TRUE(result1);
-  scoped_ptr<Class> klass2(reinterpret_cast<Class*>(new byte[sizeof(Class)]));
-  bool result2 = dex_file2->LoadClass("LProtoCompare2;", klass2.get());
+  scoped_ptr<Class> klass2(Heap::AllocClass(dex_file2.get()));
+  bool result2 = linker2.LoadClass("LProtoCompare2;", klass2.get());
   ASSERT_TRUE(result2);
 
   Method* m1_1 = klass1->GetVirtualMethod(0);
diff --git a/src/raw_dex_file.cc b/src/raw_dex_file.cc
index 145509a..2d97a9a 100644
--- a/src/raw_dex_file.cc
+++ b/src/raw_dex_file.cc
@@ -155,9 +155,9 @@
   }
 }
 
-const RawDexFile::ClassDef* RawDexFile::FindClassDef(const char* descriptor) {
+const RawDexFile::ClassDef* RawDexFile::FindClassDef(const char* descriptor) const {
   CHECK(descriptor != NULL);
-  Index::iterator it = index_.find(descriptor);
+  Index::const_iterator it = index_.find(descriptor);
   if (it == index_.end()) {
     return NULL;
   } else {
@@ -223,7 +223,7 @@
 }
 
 RawDexFile::ValueType RawDexFile::ReadEncodedValue(const byte** stream,
-                                                   JValue* value) {
+                                                   JValue* value) const {
   const byte* ptr = *stream;
   byte value_type = *ptr++;
   byte value_arg = value_type >> kEncodedValueArgShift;
diff --git a/src/raw_dex_file.h b/src/raw_dex_file.h
index db3d8a2..6f8a581 100644
--- a/src/raw_dex_file.h
+++ b/src/raw_dex_file.h
@@ -227,7 +227,7 @@
   }
 
   // Looks up a class definition by its class descriptor.
-  const ClassDef* FindClassDef(const char* descriptor);
+  const ClassDef* FindClassDef(const char* descriptor) const;
 
   // Returns the number of string identifiers in the .dex file.
   size_t NumStringIds() const {
@@ -276,7 +276,7 @@
   }
 
   // Decodes the header section from the raw class data bytes.
-  ClassDataHeader ReadClassDataHeader(const byte** class_data) {
+  ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
     CHECK(class_data != NULL);
     ClassDataHeader header;
     memset(&header, 0, sizeof(ClassDataHeader));
@@ -349,7 +349,7 @@
   }
 
   // Returns the short form method descriptor for the given prototype.
-  const char* GetShorty(uint32_t proto_idx) {
+  const char* GetShorty(uint32_t proto_idx) const {
     const ProtoId& proto_id = GetProtoId(proto_idx);
     return dexStringById(proto_id.shorty_idx_);
   }
@@ -376,7 +376,7 @@
     return DecodeUnsignedLeb128(&ptr);
   }
 
-  ValueType ReadEncodedValue(const byte** encoded_value, JValue* value);
+  ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
 
   // From libdex...
 
diff --git a/src/raw_dex_file_test.cc b/src/raw_dex_file_test.cc
index 1dd1485..8b0c130 100644
--- a/src/raw_dex_file_test.cc
+++ b/src/raw_dex_file_test.cc
@@ -1,5 +1,6 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 
+#include "src/common_test.h"
 #include "src/dex_file.h"
 #include "src/raw_dex_file.h"
 #include "src/scoped_ptr.h"
@@ -9,29 +10,6 @@
 
 namespace art {
 
-// class Nested {
-//     class Inner {
-//     }
-// }
-static const char kNestedDex[] =
-  "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP"
-  "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B"
-  "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA"
-  "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA"
-  "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA"
-  "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA"
-  "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA"
-  "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu"
-  "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2"
-  "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz"
-  "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA"
-  "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA"
-  "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH"
-  "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ"
-  "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA"
-  "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA==";
-
-
 TEST(RawDexFile, Open) {
   scoped_ptr<RawDexFile> raw(RawDexFile::OpenBase64(kNestedDex));
   ASSERT_TRUE(raw != NULL);