Merge "Hold a ClassLoader reference in NativeAllocationRegistry." into nyc-dev
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 6703695..679c274 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -609,6 +609,9 @@
                            graph->GetBlocks().size(),
                            /* expandable */ false,
                            kArenaAllocGraphBuilder);
+    // Stop marking blocks at the loop header.
+    visited.SetBit(header_->GetBlockId());
+
     for (HBasicBlock* back_edge : GetBackEdges()) {
       PopulateIrreducibleRecursive(back_edge, &visited);
     }
diff --git a/compiler/optimizing/ssa_phi_elimination.cc b/compiler/optimizing/ssa_phi_elimination.cc
index aeb3109..0978ae1 100644
--- a/compiler/optimizing/ssa_phi_elimination.cc
+++ b/compiler/optimizing/ssa_phi_elimination.cc
@@ -139,8 +139,9 @@
       continue;
     }
 
-    if (phi->InputCount() == 0) {
-      DCHECK(phi->IsDead());
+    // If the phi is dead, we know we won't revive it and it will be removed,
+    // so don't process it.
+    if (phi->IsDead()) {
       continue;
     }
 
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 6ecfc74..d2ab699 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -59,6 +59,7 @@
 #include "stack_map.h"
 #include "ScopedLocalRef.h"
 #include "thread_list.h"
+#include "type_lookup_table.h"
 #include "verifier/method_verifier.h"
 #include "well_known_classes.h"
 
@@ -573,8 +574,15 @@
     os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
     os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum());
 
-    // Create the verifier early.
+    // Print embedded dex file data range.
+    const uint8_t* const oat_file_begin = oat_dex_file.GetOatFile()->Begin();
+    const uint8_t* const dex_file_pointer = oat_dex_file.GetDexFilePointer();
+    uint32_t dex_offset = dchecked_integral_cast<uint32_t>(dex_file_pointer - oat_file_begin);
+    os << StringPrintf("dex-file: 0x%08x..0x%08x\n",
+                       dex_offset,
+                       dchecked_integral_cast<uint32_t>(dex_offset + oat_dex_file.FileSize() - 1));
 
+    // Create the dex file early. A lot of print-out things depend on it.
     std::string error_msg;
     const DexFile* const dex_file = OpenDexFile(&oat_dex_file, &error_msg);
     if (dex_file == nullptr) {
@@ -583,6 +591,16 @@
       return false;
     }
 
+    // Print lookup table, if it exists.
+    if (oat_dex_file.GetLookupTableData() != nullptr) {
+      uint32_t table_offset = dchecked_integral_cast<uint32_t>(
+          oat_dex_file.GetLookupTableData() - oat_file_begin);
+      uint32_t table_size = TypeLookupTable::RawDataLength(*dex_file);
+      os << StringPrintf("type-table: 0x%08x..0x%08x\n",
+                         table_offset,
+                         table_offset + table_size - 1);
+    }
+
     VariableIndentationOutputStream vios(&os);
     ScopedIndentation indent1(&vios);
     for (size_t class_def_index = 0;
diff --git a/profman/profman.cc b/profman/profman.cc
index 9e5bffd..4d9276f 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -215,7 +215,11 @@
   }
 
   void LogCompletionTime() {
-    LOG(INFO) << "profman took " << PrettyDuration(NanoTime() - start_ns_);
+    static constexpr uint64_t kLogThresholdTime = MsToNs(100);  // 100ms
+    uint64_t time_taken = NanoTime() - start_ns_;
+    if (time_taken > kLogThresholdTime) {
+      LOG(WARNING) << "profman took " << PrettyDuration(time_taken);
+    }
   }
 
   std::vector<std::string> profile_files_;
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 6449efa..7647ad6 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -456,13 +456,18 @@
       interface_method->VisitRoots(visitor, pointer_size);
     }
     visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
-    // Runtime methods and native methods use the same field as the profiling info for
-    // storing their own data (jni entrypoint for native methods, and ImtConflictTable for
-    // some runtime methods).
-    if (!IsNative() && !IsRuntimeMethod()) {
-      ProfilingInfo* profiling_info = GetProfilingInfo(pointer_size);
-      if (profiling_info != nullptr) {
-        profiling_info->VisitRoots(visitor);
+    // We know we don't have profiling information if the class hasn't been verified. Note
+    // that this check also ensures the IsNative call can be made, as IsNative expects a fully
+    // created class (and not a retired one).
+    if (klass->IsVerified()) {
+      // Runtime methods and native methods use the same field as the profiling info for
+      // storing their own data (jni entrypoint for native methods, and ImtConflictTable for
+      // some runtime methods).
+      if (!IsNative() && !IsRuntimeMethod()) {
+        ProfilingInfo* profiling_info = GetProfilingInfo(pointer_size);
+        if (profiling_info != nullptr) {
+          profiling_info->VisitRoots(visitor);
+        }
       }
     }
   }
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c92304f..e7a560b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -6635,6 +6635,15 @@
             // The method is not overridable by a default method (i.e. it is directly implemented
             // in some class). Therefore move onto the next interface method.
             continue;
+          } else {
+            // If the super-classes method is override-able by a default method we need to keep
+            // track of it since though it is override-able it is not guaranteed to be 'overridden'.
+            // If it turns out not to be overridden and we did not keep track of it we might add it
+            // to the vtable twice, causing corruption in this class and possibly any subclasses.
+            DCHECK(vtable_impl == nullptr || vtable_impl == supers_method)
+                << "vtable_impl was " << PrettyMethod(vtable_impl) << " and not 'nullptr' or "
+                << PrettyMethod(supers_method) << " as expected. IFTable appears to be corrupt!";
+            vtable_impl = supers_method;
           }
         }
         // If we haven't found it yet we should search through the interfaces for default methods.
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 3df4e98..7006033 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -2608,7 +2608,13 @@
       *error_msg = StringPrintf("Constructor %" PRIu32 "(%s) is not flagged correctly wrt/ static.",
                                 method_index,
                                 GetMethodDescriptionOrError(begin_, header_, method_index).c_str());
-      return false;
+      if (header_->GetVersion() >= DexFile::kDefaultMethodsVersion) {
+        return false;
+      } else {
+        // Allow in older versions, but warn.
+        LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
+                     << *error_msg;
+      }
     }
   }
   // Check that static and private methods, as well as constructors, are in the direct methods list,
@@ -2662,7 +2668,13 @@
       *error_msg = StringPrintf("Constructor %u(%s) must not be abstract or native",
                                 method_index,
                                 GetMethodDescriptionOrError(begin_, header_, method_index).c_str());
-      return false;
+      if (header_->GetVersion() >= DexFile::kDefaultMethodsVersion) {
+        return false;
+      } else {
+        // Allow in older versions, but warn.
+        LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
+                      << *error_msg;
+      }
     }
     if ((method_access_flags & kAccAbstract) != 0) {
       // Abstract methods are not allowed to have the following flags.
diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc
index 344d186..990ad5a 100644
--- a/runtime/dex_file_verifier_test.cc
+++ b/runtime/dex_file_verifier_test.cc
@@ -57,6 +57,13 @@
   255, 255, 255, 255
 };
 
+// Make the Dex file version 37.
+static void MakeDexVersion37(DexFile* dex_file) {
+  size_t offset = OFFSETOF_MEMBER(DexFile::Header, magic_) + 6;
+  CHECK_EQ(*(dex_file->Begin() + offset), '5');
+  *(const_cast<uint8_t*>(dex_file->Begin()) + offset) = '7';
+}
+
 static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
   std::vector<uint8_t> tmp;
   uint32_t t = 0, y = 0;
@@ -449,6 +456,7 @@
         kMethodFlagsTestDex,
         "method_flags_constructor_native_nocode",
         [&](DexFile* dex_file) {
+          MakeDexVersion37(dex_file);
           ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
           ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
 
@@ -461,6 +469,7 @@
         kMethodFlagsTestDex,
         "method_flags_constructor_abstract_nocode",
         [&](DexFile* dex_file) {
+          MakeDexVersion37(dex_file);
           ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
           ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
 
@@ -521,6 +530,7 @@
       kMethodFlagsTestDex,
       "init_not_allowed_flags",
       [&](DexFile* dex_file) {
+        MakeDexVersion37(dex_file);
         ApplyMaskToMethodFlags(dex_file, "foo", ~kAccDeclaredSynchronized);
         ApplyMaskToMethodFlags(dex_file, "bar", ~kAccDeclaredSynchronized);
 
@@ -725,13 +735,6 @@
   return result;
 }
 
-// Make the Dex file version 37.
-static void MakeDexVersion37(DexFile* dex_file) {
-  size_t offset = OFFSETOF_MEMBER(DexFile::Header, magic_) + 6;
-  CHECK_EQ(*(dex_file->Begin() + offset), '5');
-  *(const_cast<uint8_t*>(dex_file->Begin()) + offset) = '7';
-}
-
 TEST_F(DexFileVerifierTest, MethodAccessFlagsInterfaces) {
   VerifyModification(
       kMethodFlagsInterface,
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index e9317a5..dcc6300 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -103,13 +103,13 @@
   }
 
   if (options.Exists(RuntimeArgumentMap::JITInvokeTransitionWeight)) {
+    jit_options->invoke_transition_weight_ =
+        *options.Get(RuntimeArgumentMap::JITInvokeTransitionWeight);
     if (jit_options->invoke_transition_weight_ > jit_options->warmup_threshold_) {
       LOG(FATAL) << "Invoke transition weight is above the warmup threshold.";
     } else if (jit_options->invoke_transition_weight_  == 0) {
-      LOG(FATAL) << "Invoke transition ratio cannot be 0.";
+      LOG(FATAL) << "Invoke transition weight cannot be 0.";
     }
-    jit_options->invoke_transition_weight_ =
-        *options.Get(RuntimeArgumentMap::JITInvokeTransitionWeight);
   } else {
     jit_options->invoke_transition_weight_ = std::max(
         jit_options->warmup_threshold_ / Jit::kDefaultInvokeTransitionWeightRatio,
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 6b7ca40..0624da3 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -238,12 +238,13 @@
   DCHECK(name != nullptr);
   DCHECK(self != nullptr);
 
-  StackHandleScope<1> hs(self);
+  StackHandleScope<2> hs(self);
   MutableHandle<mirror::Class> h_clazz(hs.NewHandle(clazz));
+  Handle<mirror::String> h_name(hs.NewHandle(name));
 
   // We search the current class, its direct interfaces then its superclass.
   while (h_clazz.Get() != nullptr) {
-    mirror::Field* result = GetDeclaredField(self, h_clazz.Get(), name);
+    mirror::Field* result = GetDeclaredField(self, h_clazz.Get(), h_name.Get());
     if ((result != nullptr) && (result->GetAccessFlags() & kAccPublic)) {
       return result;
     } else if (UNLIKELY(self->IsExceptionPending())) {
@@ -258,7 +259,7 @@
         self->AssertPendingException();
         return nullptr;
       }
-      result = GetPublicFieldRecursive(self, iface, name);
+      result = GetPublicFieldRecursive(self, iface, h_name.Get());
       if (result != nullptr) {
         DCHECK(result->GetAccessFlags() & kAccPublic);
         return result;
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index b58be92..aa727ff 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -373,6 +373,10 @@
     return lookup_table_data_;
   }
 
+  const uint8_t* GetDexFilePointer() const {
+    return dex_file_pointer_;
+  }
+
   ~OatDexFile();
 
  private:
diff --git a/test/596-checker-dead-phi/expected.txt b/test/596-checker-dead-phi/expected.txt
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/test/596-checker-dead-phi/expected.txt
@@ -0,0 +1 @@
+42
diff --git a/test/596-checker-dead-phi/info.txt b/test/596-checker-dead-phi/info.txt
new file mode 100644
index 0000000..7f7cf0f
--- /dev/null
+++ b/test/596-checker-dead-phi/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing where we used to replace a dead loop
+phi with its first incoming input.
diff --git a/test/596-checker-dead-phi/smali/IrreducibleLoop.smali b/test/596-checker-dead-phi/smali/IrreducibleLoop.smali
new file mode 100644
index 0000000..bab2ba9
--- /dev/null
+++ b/test/596-checker-dead-phi/smali/IrreducibleLoop.smali
@@ -0,0 +1,74 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LIrreducibleLoop;
+
+.super Ljava/lang/Object;
+
+# Test case where liveness analysis produces linear order where loop blocks are
+# not adjacent. This revealed a bug in our SSA builder, where a dead loop phi would
+# be replaced by its incoming input during SsaRedundantPhiElimination.
+
+# Check that the outer loop suspend check environment only has the parameter vreg.
+## CHECK-START: int IrreducibleLoop.liveness(int) builder (after)
+## CHECK-DAG:     <<Phi:i\d+>> Phi reg:4 loop:{{B\d+}} irreducible:false
+## CHECK-DAG:     SuspendCheck env:[[_,_,_,_,<<Phi>>]] loop:{{B\d+}} irreducible:false
+
+# Check that the linear order has non-adjacent loop blocks.
+## CHECK-START: int IrreducibleLoop.liveness(int) liveness (after)
+## CHECK-DAG:     Mul liveness:<<LPreEntry2:\d+>>
+## CHECK-DAG:     Add liveness:<<LBackEdge1:\d+>>
+## CHECK-EVAL:    <<LBackEdge1>> < <<LPreEntry2>>
+
+.method public static liveness(I)I
+    .registers 5
+
+    const-string v1, "MyString"
+
+    :header1
+    if-eqz p0, :body1
+
+    :exit
+    return p0
+
+    :body1
+    # The test will generate an incorrect linear order when the following IF swaps
+    # its successors. To do that, load a boolean value and compare NotEqual to 1.
+    sget-boolean v2, LIrreducibleLoop;->f:Z
+    const v3, 1
+    if-ne v2, v3, :pre_header2
+
+    :pre_entry2
+    # Add a marker on the irreducible loop entry.
+    mul-int/2addr p0, p0
+    goto :back_edge2
+
+    :back_edge2
+    goto :header2
+
+    :header2
+    if-eqz p0, :back_edge2
+
+    :back_edge1
+    # Add a marker on the outer loop back edge.
+    add-int/2addr p0, p0
+    # Set a wide register, to have v1 undefined at the back edge.
+    const-wide/16 v0, 0x1
+    goto :header1
+
+    :pre_header2
+    goto :header2
+.end method
+
+.field public static f:Z
diff --git a/test/596-checker-dead-phi/src/Main.java b/test/596-checker-dead-phi/src/Main.java
new file mode 100644
index 0000000..5a3fffc
--- /dev/null
+++ b/test/596-checker-dead-phi/src/Main.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+
+public class Main {
+  // Workaround for b/18051191.
+  class InnerClass {}
+
+  public static void main(String[] args) throws Exception {
+    Class<?> c = Class.forName("IrreducibleLoop");
+    // Note that we don't actually enter the loops in the 'liveness'
+    // method, so this is just a sanity check that part of the code we
+    // generated for that method is correct.
+    Method m = c.getMethod("liveness", int.class);
+    Object[] arguments = { 42 };
+    System.out.println(m.invoke(null, arguments));
+  }
+}
diff --git a/test/960-default-smali/expected.txt b/test/960-default-smali/expected.txt
index 7671eed..f3db93f 100644
--- a/test/960-default-smali/expected.txt
+++ b/test/960-default-smali/expected.txt
@@ -82,3 +82,19 @@
 J-interface   Greeter.SayHiTwice()='Hi Hi '
 J-virtual           J.SayHiTwice()='Hi Hi '
 End testing for type J
+Testing for type K
+K-interface       Foo.bar()='foobar'
+K-virtual           K.bar()='foobar'
+End testing for type K
+Testing for type L
+L-interface       Foo.bar()='foobar'
+L-virtual           K.bar()='foobar'
+L-virtual           L.bar()='foobar'
+End testing for type L
+Testing for type M
+M-interface       Foo.bar()='BAZ!'
+M-interface     Fooer.bar()='BAZ!'
+M-virtual           K.bar()='BAZ!'
+M-virtual           L.bar()='BAZ!'
+M-virtual           M.bar()='BAZ!'
+End testing for type M
diff --git a/test/960-default-smali/src/Foo.java b/test/960-default-smali/src/Foo.java
new file mode 100644
index 0000000..ed5b35f
--- /dev/null
+++ b/test/960-default-smali/src/Foo.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+interface Foo {
+  public default String bar() {
+    return "foobar";
+  }
+}
diff --git a/test/960-default-smali/src/Fooer.java b/test/960-default-smali/src/Fooer.java
new file mode 100644
index 0000000..d8a5f61
--- /dev/null
+++ b/test/960-default-smali/src/Fooer.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface Fooer extends Foo {
+  public String bar();
+}
diff --git a/test/960-default-smali/src/K.java b/test/960-default-smali/src/K.java
new file mode 100644
index 0000000..4426be7
--- /dev/null
+++ b/test/960-default-smali/src/K.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class K implements Foo { }
diff --git a/test/960-default-smali/src/L.java b/test/960-default-smali/src/L.java
new file mode 100644
index 0000000..c08ab72
--- /dev/null
+++ b/test/960-default-smali/src/L.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class L extends K { }
diff --git a/test/960-default-smali/src/M.java b/test/960-default-smali/src/M.java
new file mode 100644
index 0000000..affe7e9
--- /dev/null
+++ b/test/960-default-smali/src/M.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class M extends L implements Fooer {
+  public String bar() {
+    return "BAZ!";
+  }
+}
diff --git a/test/960-default-smali/src/classes.xml b/test/960-default-smali/src/classes.xml
index 0aa41f7..f3e50c5 100644
--- a/test/960-default-smali/src/classes.xml
+++ b/test/960-default-smali/src/classes.xml
@@ -81,6 +81,27 @@
       <implements> </implements>
       <methods> </methods>
     </class>
+
+    <class name="K" super="java/lang/Object">
+      <implements>
+        <item>Foo</item>
+      </implements>
+      <methods> </methods>
+    </class>
+
+    <class name="L" super="K">
+      <implements> </implements>
+      <methods> </methods>
+    </class>
+
+    <class name="M" super="L">
+      <implements>
+        <item>Fooer</item>
+      </implements>
+      <methods>
+        <method>bar</method>
+      </methods>
+    </class>
   </classes>
 
   <interfaces>
@@ -123,5 +144,22 @@
         <method type="abstract">GetPlace</method>
       </methods>
     </interface>
+
+    <interface name="Foo" super="java/lang/Object">
+      <implements>
+      </implements>
+      <methods>
+        <method type="default">bar</method>
+      </methods>
+    </interface>
+
+    <interface name="Fooer" super="java/lang/Object">
+      <implements>
+        <item>Foo</item>
+      </implements>
+      <methods>
+        <method type="abstract">bar</method>
+      </methods>
+    </interface>
   </interfaces>
 </data>
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index d61fc8f..a02fe95 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -476,11 +476,14 @@
       LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBRARY_DIRECTORY
     fi
 
+    PUBLIC_LIBS=libart.so:libartd.so
+
     # Create a script with the command. The command can get longer than the longest
     # allowed adb command and there is no way to get the exit status from a adb shell
     # command.
     cmdline="cd $DEX_LOCATION && \
              export ANDROID_DATA=$DEX_LOCATION && \
+             export ANDROID_ADDITIONAL_PUBLIC_LIBRARIES=$PUBLIC_LIBS && \
              export DEX_LOCATION=$DEX_LOCATION && \
              export ANDROID_ROOT=$ANDROID_ROOT && \
              $mkdir_cmdline && \
diff --git a/test/run-test b/test/run-test
index fc57d09..ce8c010 100755
--- a/test/run-test
+++ b/test/run-test
@@ -467,7 +467,7 @@
         run_args="${run_args} --runtime-option -Djava.library.path=${ANDROID_HOST_OUT}/lib${suffix64}"
     else
         guess_target_arch_name
-        run_args="${run_args} --runtime-option -Djava.library.path=/data/art-test/${target_arch_name}"
+        run_args="${run_args} --runtime-option -Djava.library.path=/data/art-test/${target_arch_name}:/system/lib${suffix64}"
         run_args="${run_args} --boot /data/art-test/core${image_suffix}${pic_image_suffix}${multi_image_suffix}.art"
     fi
     if [ "$relocate" = "yes" ]; then