Remove hard-coded Object class from test 980
We redefined Object to a hard-coded dex-file in test 980. This led to
problems whenever anything tried to change the Object class. This
change makes us use slicer to modify the Object class instead.
Test: ./test.py --host
Change-Id: Ic888281f57f5796ec4a284ce79fa322669266899
diff --git a/test/980-redefine-object/redef_object.cc b/test/980-redefine-object/redef_object.cc
new file mode 100644
index 0000000..b4d82ad
--- /dev/null
+++ b/test/980-redefine-object/redef_object.cc
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <limits>
+#include <memory>
+
+#include "jni.h"
+#include "jvmti.h"
+
+// Test infrastructure
+#include "jvmti_helper.h"
+#include "test_env.h"
+
+// Slicer's headers have code that triggers these warnings. b/65298177
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsign-compare"
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#include "slicer/instrumentation.h"
+#include "slicer/reader.h"
+#include "slicer/writer.h"
+#pragma clang diagnostic pop
+
+namespace art {
+namespace Test980RedefineObject {
+
+static void JNICALL RedefineObjectHook(jvmtiEnv *jvmti_env,
+ JNIEnv* env,
+ jclass class_being_redefined ATTRIBUTE_UNUSED,
+ jobject loader ATTRIBUTE_UNUSED,
+ const char* name,
+ jobject protection_domain ATTRIBUTE_UNUSED,
+ jint class_data_len,
+ const unsigned char* class_data,
+ jint* new_class_data_len,
+ unsigned char** new_class_data) {
+ if (strcmp(name, "java/lang/Object") != 0) {
+ return;
+ }
+
+ dex::Reader reader(class_data, class_data_len);
+ dex::u4 class_index = reader.FindClassIndex("Ljava/lang/Object;");
+ if (class_index == dex::kNoIndex) {
+ env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
+ "Failed to find object in dex file!");
+ return;
+ }
+
+ reader.CreateClassIr(class_index);
+ auto dex_ir = reader.GetIr();
+
+ slicer::MethodInstrumenter mi(dex_ir);
+ mi.AddTransformation<slicer::EntryHook>(ir::MethodId("Lart/test/TestWatcher;",
+ "NotifyConstructed"),
+ /*this_as_object*/ true);
+ if (!mi.InstrumentMethod(ir::MethodId("Ljava/lang/Object;",
+ "<init>",
+ "()V"))) {
+ env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
+ "Failed to find Object;-><init>()V in dex file!");
+ return;
+ }
+
+
+ dex::Writer writer(dex_ir);
+
+ class JvmtiAllocator : public dex::Writer::Allocator {
+ public:
+ explicit JvmtiAllocator(jvmtiEnv* jvmti) : jvmti_(jvmti) {}
+
+ void* Allocate(size_t size) {
+ unsigned char* res = nullptr;
+ jvmti_->Allocate(size, &res);
+ return res;
+ }
+
+ void Free(void* ptr) {
+ jvmti_->Deallocate(reinterpret_cast<unsigned char*>(ptr));
+ }
+
+ private:
+ jvmtiEnv* jvmti_;
+ };
+ JvmtiAllocator allocator(jvmti_env);
+ size_t new_size;
+ *new_class_data = writer.CreateImage(&allocator, &new_size);
+ if (new_size > std::numeric_limits<jint>::max()) {
+ *new_class_data = nullptr;
+ env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
+ "transform result is too large!");
+ return;
+ }
+ *new_class_data_len = static_cast<jint>(new_size);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_addMemoryTrackingCall(JNIEnv* env,
+ jclass klass ATTRIBUTE_UNUSED,
+ jclass obj_class,
+ jthread thr) {
+ jvmtiCapabilities caps {.can_retransform_classes = 1};
+ if (JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps))) {
+ return;
+ }
+ jvmtiEventCallbacks cb {.ClassFileLoadHook = RedefineObjectHook };
+ if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)))) {
+ return;
+ }
+ if (JvmtiErrorToException(env,
+ jvmti_env,
+ jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+ JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
+ thr))) {
+ return;
+ }
+ if (JvmtiErrorToException(env,
+ jvmti_env,
+ jvmti_env->RetransformClasses(1, &obj_class))) {
+ return;
+ }
+ if (JvmtiErrorToException(env,
+ jvmti_env,
+ jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+ JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
+ thr))) {
+ return;
+ }
+}
+
+} // namespace Test980RedefineObject
+} // namespace art
+
diff --git a/test/980-redefine-object/src/Main.java b/test/980-redefine-object/src/Main.java
index 2428b55..efbc75f 100644
--- a/test/980-redefine-object/src/Main.java
+++ b/test/980-redefine-object/src/Main.java
@@ -14,278 +14,16 @@
* limitations under the License.
*/
-import static art.Redefinition.doCommonClassRedefinition;
-
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Base64;
import java.util.LinkedList;
public class Main {
-
- // TODO We should make this run on the RI.
/**
- * This test cannot be run on the RI.
+ * NB This test cannot be run on the RI.
+ * TODO We should make this run on the RI.
*/
- private static final byte[] CLASS_BYTES = new byte[0];
-
- // TODO It might be a good idea to replace this hard-coded Object definition with a
- // retransformation based test.
- /**
- * Base64 encoding of the following smali file.
- *
- * .class public Ljava/lang/Object;
- * .source "Object.java"
- * # instance fields
- * .field private transient shadow$_klass_:Ljava/lang/Class;
- * .annotation system Ldalvik/annotation/Signature;
- * value = {
- * "Ljava/lang/Class",
- * "<*>;"
- * }
- * .end annotation
- * .end field
- *
- * .field private transient shadow$_monitor_:I
- * # direct methods
- * .method public constructor <init>()V
- * .registers 1
- * .prologue
- * invoke-static {p0}, Lart/test/TestWatcher;->NotifyConstructed(Ljava/lang/Object;)V
- * return-void
- * .end method
- *
- * .method static identityHashCode(Ljava/lang/Object;)I
- * .registers 7
- * .prologue
- * iget v0, p0, Ljava/lang/Object;->shadow$_monitor_:I
- * const/high16 v3, -0x40000000 # -2.0f
- * const/high16 v2, -0x80000000
- * const v1, 0xfffffff
- * const/high16 v4, -0x40000000 # -2.0f
- * and-int/2addr v4, v0
- * const/high16 v5, -0x80000000
- * if-ne v4, v5, :cond_15
- * const v4, 0xfffffff
- * and-int/2addr v4, v0
- * return v4
- * :cond_15
- * invoke-static {p0}, Ljava/lang/Object;->identityHashCodeNative(Ljava/lang/Object;)I
- * move-result v4
- * return v4
- * .end method
- *
- * .method private static native identityHashCodeNative(Ljava/lang/Object;)I
- * .annotation build Ldalvik/annotation/optimization/FastNative;
- * .end annotation
- * .end method
- *
- * .method private native internalClone()Ljava/lang/Object;
- * .annotation build Ldalvik/annotation/optimization/FastNative;
- * .end annotation
- * .end method
- *
- *
- * # virtual methods
- * .method protected clone()Ljava/lang/Object;
- * .registers 4
- * .annotation system Ldalvik/annotation/Throws;
- * value = {
- * Ljava/lang/CloneNotSupportedException;
- * }
- * .end annotation
- *
- * .prologue
- * instance-of v0, p0, Ljava/lang/Cloneable;
- * if-nez v0, :cond_2d
- * new-instance v0, Ljava/lang/CloneNotSupportedException;
- * new-instance v1, Ljava/lang/StringBuilder;
- * invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
- * const-string/jumbo v2, "Class "
- * invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
- * move-result-object v1
- * invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
- * move-result-object v2
- * invoke-virtual {v2}, Ljava/lang/Class;->getName()Ljava/lang/String;
- * move-result-object v2
- * invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
- * move-result-object v1
- * const-string/jumbo v2, " doesn\'t implement Cloneable"
- * invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
- * move-result-object v1
- * invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
- * move-result-object v1
- * invoke-direct {v0, v1}, Ljava/lang/CloneNotSupportedException;-><init>(Ljava/lang/String;)V
- * throw v0
- * :cond_2d
- * invoke-direct {p0}, Ljava/lang/Object;->internalClone()Ljava/lang/Object;
- * move-result-object v0
- * return-object v0
- * .end method
- *
- * .method public equals(Ljava/lang/Object;)Z
- * .registers 3
- * .prologue
- * if-ne p0, p1, :cond_4
- * const/4 v0, 0x1
- * :goto_3
- * return v0
- * :cond_4
- * const/4 v0, 0x0
- * goto :goto_3
- * .end method
- *
- * .method protected finalize()V
- * .registers 1
- * .annotation system Ldalvik/annotation/Throws;
- * value = {
- * Ljava/lang/Throwable;
- * }
- * .end annotation
- * .prologue
- * return-void
- * .end method
- *
- * .method public final getClass()Ljava/lang/Class;
- * .registers 2
- * .annotation system Ldalvik/annotation/Signature;
- * value = {
- * "()",
- * "Ljava/lang/Class",
- * "<*>;"
- * }
- * .end annotation
- * .prologue
- * iget-object v0, p0, Ljava/lang/Object;->shadow$_klass_:Ljava/lang/Class;
- * return-object v0
- * .end method
- *
- * .method public hashCode()I
- * .registers 2
- * .prologue
- * invoke-static {p0}, Ljava/lang/Object;->identityHashCode(Ljava/lang/Object;)I
- * move-result v0
- * return v0
- * .end method
- *
- * .method public final native notify()V
- * .annotation build Ldalvik/annotation/optimization/FastNative;
- * .end annotation
- * .end method
- *
- * .method public final native notifyAll()V
- * .annotation build Ldalvik/annotation/optimization/FastNative;
- * .end annotation
- * .end method
- *
- * .method public toString()Ljava/lang/String;
- * .registers 3
- * .prologue
- * new-instance v0, Ljava/lang/StringBuilder;
- * invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V
- * invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
- * move-result-object v1
- * invoke-virtual {v1}, Ljava/lang/Class;->getName()Ljava/lang/String;
- * move-result-object v1
- * invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
- * move-result-object v0
- * const-string/jumbo v1, "@"
- * invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
- * move-result-object v0
- * invoke-virtual {p0}, Ljava/lang/Object;->hashCode()I
- * move-result v1
- * invoke-static {v1}, Ljava/lang/Integer;->toHexString(I)Ljava/lang/String;
- * move-result-object v1
- * invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
- * move-result-object v0
- * invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
- * move-result-object v0
- * return-object v0
- * .end method
- *
- * .method public final native wait()V
- * .annotation system Ldalvik/annotation/Throws;
- * value = {
- * Ljava/lang/InterruptedException;
- * }
- * .end annotation
- *
- * .annotation build Ldalvik/annotation/optimization/FastNative;
- * .end annotation
- * .end method
- *
- * .method public final wait(J)V
- * .registers 4
- * .annotation system Ldalvik/annotation/Throws;
- * value = {
- * Ljava/lang/InterruptedException;
- * }
- * .end annotation
- * .prologue
- * const/4 v0, 0x0
- * invoke-virtual {p0, p1, p2, v0}, Ljava/lang/Object;->wait(JI)V
- * return-void
- * .end method
- *
- * .method public final native wait(JI)V
- * .annotation system Ldalvik/annotation/Throws;
- * value = {
- * Ljava/lang/InterruptedException;
- * }
- * .end annotation
- *
- * .annotation build Ldalvik/annotation/optimization/FastNative;
- * .end annotation
- * .end method
- */
- private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
- "ZGV4CjAzNQDUlMR9j03MYuOKekKs2p7zJzu2IfDb7RlMCgAAcAAAAHhWNBIAAAAAAAAAAIgJAAA6" +
- "AAAAcAAAABEAAABYAQAADQAAAJwBAAACAAAAOAIAABYAAABIAgAAAQAAAPgCAAA0BwAAGAMAABgD" +
- "AAA2AwAAOgMAAEADAABIAwAASwMAAFMDAABWAwAAWgMAAF0DAABgAwAAZAMAAGgDAACAAwAAnwMA" +
- "ALsDAADoAwAA+gMAAA0EAAA1BAAATAQAAGEEAACDBAAAlwQAAKsEAADGBAAA3QQAAPAEAAD9BAAA" +
- "AAUAAAQFAAAJBQAADQUAABAFAAAUBQAAHAUAACMFAAArBQAANQUAAD8FAABIBQAAUgUAAGQFAAB8" +
- "BQAAiwUAAJUFAACnBQAAugUAAM0FAADVBQAA3QUAAOgFAADtBQAA/QUAAA8GAAAcBgAAJgYAAC0G" +
- "AAAGAAAACAAAAAwAAAANAAAADgAAAA8AAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAAXAAAAGAAA" +
- "ABkAAAAcAAAAIAAAAAYAAAAAAAAAAAAAAAcAAAAAAAAAPAYAAAkAAAAGAAAAAAAAAAkAAAALAAAA" +
- "AAAAAAkAAAAMAAAAAAAAAAoAAAAMAAAARAYAAAsAAAANAAAAVAYAABwAAAAPAAAAAAAAAB0AAAAP" +
- "AAAATAYAAB4AAAAPAAAANAYAAB8AAAAPAAAAPAYAAB8AAAAPAAAAVAYAACEAAAAQAAAAPAYAAAsA" +
- "BgA0AAAACwAAADUAAAACAAoAGgAAAAYABAAnAAAABwALAAMAAAAJAAUANgAAAAsABwADAAAACwAD" +
- "ACMAAAALAAwAJAAAAAsABwAlAAAACwACACYAAAALAAAAKAAAAAsAAQApAAAACwABACoAAAALAAMA" +
- "KwAAAAsABwAxAAAACwAHADIAAAALAAQANwAAAAsABwA5AAAACwAIADkAAAALAAkAOQAAAA0ABwAD" +
- "AAAADQAGACIAAAANAAQANwAAAAsAAAABAAAA/////wAAAAAbAAAA0AYAAD4JAAAAAAAAHCBkb2Vz" +
- "bid0IGltcGxlbWVudCBDbG9uZWFibGUAAigpAAQ8Kj47AAY8aW5pdD4AAUAABkNsYXNzIAABSQAC" +
- "SUwAAUoAAUwAAkxJAAJMTAAWTGFydC90ZXN0L1Rlc3RXYXRjaGVyOwAdTGRhbHZpay9hbm5vdGF0" +
- "aW9uL1NpZ25hdHVyZTsAGkxkYWx2aWsvYW5ub3RhdGlvbi9UaHJvd3M7ACtMZGFsdmlrL2Fubm90" +
- "YXRpb24vb3B0aW1pemF0aW9uL0Zhc3ROYXRpdmU7ABBMamF2YS9sYW5nL0NsYXNzABFMamF2YS9s" +
- "YW5nL0NsYXNzOwAmTGphdmEvbGFuZy9DbG9uZU5vdFN1cHBvcnRlZEV4Y2VwdGlvbjsAFUxqYXZh" +
- "L2xhbmcvQ2xvbmVhYmxlOwATTGphdmEvbGFuZy9JbnRlZ2VyOwAgTGphdmEvbGFuZy9JbnRlcnJ1" +
- "cHRlZEV4Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlM" +
- "amF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7ABVMamF2YS9sYW5nL1Rocm93YWJsZTsAEU5vdGlmeUNv" +
- "bnN0cnVjdGVkAAtPYmplY3QuamF2YQABVgACVkoAA1ZKSQACVkwAAVoAAlpMAAZhcHBlbmQABWNs" +
- "b25lAAZlcXVhbHMACGZpbmFsaXplAAhnZXRDbGFzcwAHZ2V0TmFtZQAIaGFzaENvZGUAEGlkZW50" +
- "aXR5SGFzaENvZGUAFmlkZW50aXR5SGFzaENvZGVOYXRpdmUADWludGVybmFsQ2xvbmUACGxvY2tX" +
- "b3JkABBsb2NrV29yZEhhc2hNYXNrABFsb2NrV29yZFN0YXRlSGFzaAARbG9ja1dvcmRTdGF0ZU1h" +
- "c2sABm1pbGxpcwAGbm90aWZ5AAlub3RpZnlBbGwAA29iagAOc2hhZG93JF9rbGFzc18AEHNoYWRv" +
- "dyRfbW9uaXRvcl8AC3RvSGV4U3RyaW5nAAh0b1N0cmluZwAFdmFsdWUABHdhaXQAAAIAAAABAAAA" +
- "AQAAAAsAAAABAAAAAAAAAAEAAAABAAAAAQAAAAwAAgQBOBwBGAcCBAE4HAEYCgIDATgcAhcQFwIC" +
- "BAE4HAEYDgAFAAIDATgcAxcBFxAXAgAAAAAAAAAAAAEAAABaBgAAAgAAAGIGAAB8BgAAAQAAAGIG" +
- "AAABAAAAagYAAAEAAAB0BgAAAQAAAHwGAAABAAAAfwYAAAAAAAABAAAACgAAAAAAAAAAAAAAsAYA" +
- "AAUAAACUBgAABwAAALgGAAAIAAAAyAYAAAsAAADABgAADAAAAMAGAAANAAAAwAYAAA4AAADABgAA" +
- "EAAAAJwGAAARAAAAqAYAABIAAACcBgAAKAAHDgBwATQHDi0DAC0BLQMDMAEtAwIvATwDAS4BeFsA" +
- "7AEABw5LARoPOsYArAEBNAcOAMUEAAcOAEEABw4AaAAHDgCRAgAHDgCmAwExBw5LAAAAAQABAAEA" +
- "AAA4BwAABAAAAHEQAAAAAA4ABwABAAEAAAA9BwAAGgAAAFJgAQAVAwDAFQIAgBQB////DxUEAMC1" +
- "BBUFAIAzVAcAFAT///8PtQQPBHEQCwAGAAoEDwQEAAEAAgAAAFkHAAAyAAAAIDAIADkAKwAiAAcA" +
- "IgENAHAQEwABABsCBQAAAG4gFAAhAAwBbhAIAAMADAJuEAEAAgAMAm4gFAAhAAwBGwIAAAAAbiAU" +
- "ACEADAFuEBUAAQAMAXAgAgAQACcAcBAMAAMADAARAAMAAgAAAAAAZQcAAAYAAAAzIQQAEhAPABIA" +
- "KP4BAAEAAAAAAGwHAAABAAAADgAAAAIAAQAAAAAAcgcAAAMAAABUEAAAEQAAAAIAAQABAAAAdwcA" +
- "AAUAAABxEAoAAQAKAA8AAAADAAEAAgAAAHwHAAApAAAAIgANAHAQEwAAAG4QCAACAAwBbhABAAEA" +
- "DAFuIBQAEAAMABsBBAAAAG4gFAAQAAwAbhAJAAIACgFxEAMAAQAMAW4gFAAQAAwAbhAVAAAADAAR" +
- "AAAABAADAAQAAACCBwAABQAAABIAbkASACEDDgAAAgQLAIIBAYIBBIGABIwPBgikDwGKAgABggIA" +
- "BQToDwEB3BABBPgQARGMEQEBpBEEkQIAAZECAAEBwBEBkQIAARGkEgGRAgAAABAAAAAAAAAAAQAA" +
- "AAAAAAABAAAAOgAAAHAAAAACAAAAEQAAAFgBAAADAAAADQAAAJwBAAAEAAAAAgAAADgCAAAFAAAA" +
- "FgAAAEgCAAAGAAAAAQAAAPgCAAACIAAAOgAAABgDAAABEAAABQAAADQGAAAEIAAABgAAAFoGAAAD" +
- "EAAACQAAAIwGAAAGIAAAAQAAANAGAAADIAAACQAAADgHAAABIAAACQAAAIwHAAAAIAAAAQAAAD4J" +
- "AAAAEAAAAQAAAIgJAAA=");
private static final String LISTENER_LOCATION =
System.getenv("DEX_LOCATION") + "/980-redefine-object-ex.jar";
@@ -361,7 +99,7 @@
// Redefine the Object Class.
safePrintln("Redefining the Object class to add a hook into the <init> method");
- doCommonClassRedefinition(Object.class, CLASS_BYTES, DEX_BYTES);
+ addMemoryTrackingCall(Object.class, Thread.currentThread());
safePrintln("Allocating an j.l.Object after redefining Object class");
Object o2 = new Object();
@@ -407,5 +145,10 @@
safePrintln("Finishing test!");
}
+ // This is from 929-search/search.cc
private static native void addToBootClassLoader(String s);
+ // This is from 980-redefine-object/redef_object.cc
+ // It will add a call to Lart/test/TestWatcher;->NotifyConstructed()V in the Object <init>()V
+ // function.
+ private static native void addMemoryTrackingCall(Class c, Thread thr);
}
diff --git a/test/980-redefine-object/src/art/Redefinition.java b/test/980-redefine-object/src/art/Redefinition.java
deleted file mode 100644
index 56d2938..0000000
--- a/test/980-redefine-object/src/art/Redefinition.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-package art;
-
-import java.util.ArrayList;
-// Common Redefinition functions. Placed here for use by CTS
-public class Redefinition {
- public static final class CommonClassDefinition {
- public final Class<?> target;
- public final byte[] class_file_bytes;
- public final byte[] dex_file_bytes;
-
- public CommonClassDefinition(Class<?> target, byte[] class_file_bytes, byte[] dex_file_bytes) {
- this.target = target;
- this.class_file_bytes = class_file_bytes;
- this.dex_file_bytes = dex_file_bytes;
- }
- }
-
- // A set of possible test configurations. Test should set this if they need to.
- // This must be kept in sync with the defines in ti-agent/common_helper.cc
- public static enum Config {
- COMMON_REDEFINE(0),
- COMMON_RETRANSFORM(1),
- COMMON_TRANSFORM(2);
-
- private final int val;
- private Config(int val) {
- this.val = val;
- }
- }
-
- public static void setTestConfiguration(Config type) {
- nativeSetTestConfiguration(type.val);
- }
-
- private static native void nativeSetTestConfiguration(int type);
-
- // Transforms the class
- public static native void doCommonClassRedefinition(Class<?> target,
- byte[] classfile,
- byte[] dexfile);
-
- public static void doMultiClassRedefinition(CommonClassDefinition... defs) {
- ArrayList<Class<?>> classes = new ArrayList<>();
- ArrayList<byte[]> class_files = new ArrayList<>();
- ArrayList<byte[]> dex_files = new ArrayList<>();
-
- for (CommonClassDefinition d : defs) {
- classes.add(d.target);
- class_files.add(d.class_file_bytes);
- dex_files.add(d.dex_file_bytes);
- }
- doCommonMultiClassRedefinition(classes.toArray(new Class<?>[0]),
- class_files.toArray(new byte[0][]),
- dex_files.toArray(new byte[0][]));
- }
-
- public static void addMultiTransformationResults(CommonClassDefinition... defs) {
- for (CommonClassDefinition d : defs) {
- addCommonTransformationResult(d.target.getCanonicalName(),
- d.class_file_bytes,
- d.dex_file_bytes);
- }
- }
-
- public static native void doCommonMultiClassRedefinition(Class<?>[] targets,
- byte[][] classfiles,
- byte[][] dexfiles);
- public static native void doCommonClassRetransformation(Class<?>... target);
- public static native void setPopRetransformations(boolean pop);
- public static native void popTransformationFor(String name);
- public static native void enableCommonRetransformation(boolean enable);
- public static native void addCommonTransformationResult(String target_name,
- byte[] class_bytes,
- byte[] dex_bytes);
-}
diff --git a/test/Android.bp b/test/Android.bp
index 7909bf8..e0ec286 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -314,10 +314,15 @@
"909-attach-agent/attach.cc",
"912-classes/classes_art.cc",
"936-search-onload/search_onload.cc",
+ "980-redefine-object/redef_object.cc",
"983-source-transform-verify/source_transform_art.cc",
"1940-ddms-ext/ddm_ext.cc",
"1944-sudden-exit/sudden_exit.cc",
],
+ static_libs: [
+ "libz",
+ "slicer",
+ ],
}
art_cc_test_library {