ART: Add allocation callback
Bug: 31684277
Test: m test-art-host
Change-Id: I959f44e23ca5fe55ed678315708895faf0aadb04
diff --git a/test/904-object-allocation/build b/test/904-object-allocation/build
new file mode 100755
index 0000000..898e2e5
--- /dev/null
+++ b/test/904-object-allocation/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/904-object-allocation/expected.txt b/test/904-object-allocation/expected.txt
new file mode 100644
index 0000000..371d2b7
--- /dev/null
+++ b/test/904-object-allocation/expected.txt
@@ -0,0 +1,8 @@
+ObjectAllocated type java.lang.Object/java.lang.Object size 8
+ObjectAllocated type java.lang.Integer/java.lang.Integer size 16
+ObjectAllocated type java.lang.Short/java.lang.Short size 16
+Tracking on same thread
+ObjectAllocated type java.lang.Double/java.lang.Double size 16
+Tracking on same thread, not disabling tracking
+ObjectAllocated type java.lang.Double/java.lang.Double size 16
+Tracking on different thread
diff --git a/test/904-object-allocation/info.txt b/test/904-object-allocation/info.txt
new file mode 100644
index 0000000..875a5f6
--- /dev/null
+++ b/test/904-object-allocation/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/904-object-allocation/run b/test/904-object-allocation/run
new file mode 100755
index 0000000..2f7ad21
--- /dev/null
+++ b/test/904-object-allocation/run
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# 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.
+
+plugin=libopenjdkjvmtid.so
+agent=libtiagentd.so
+lib=tiagentd
+if [[ "$@" == *"-O"* ]]; then
+ agent=libtiagent.so
+ plugin=libopenjdkjvmti.so
+ lib=tiagent
+fi
+
+if [[ "$@" == *"--jvm"* ]]; then
+ arg="jvm"
+else
+ arg="art"
+fi
+
+if [[ "$@" != *"--debuggable"* ]]; then
+ other_args=" -Xcompiler-option --debuggable "
+else
+ other_args=""
+fi
+
+./default-run "$@" --experimental agents \
+ --experimental runtime-plugins \
+ --runtime-option -agentpath:${agent}=904-object-allocation,${arg} \
+ --android-runtime-option -Xplugin:${plugin} \
+ ${other_args} \
+ --args ${lib}
diff --git a/test/904-object-allocation/src/Main.java b/test/904-object-allocation/src/Main.java
new file mode 100644
index 0000000..63f7f89
--- /dev/null
+++ b/test/904-object-allocation/src/Main.java
@@ -0,0 +1,119 @@
+/*
+ * 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.util.ArrayList;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[1]);
+
+ // Use a list to ensure objects must be allocated.
+ ArrayList<Object> l = new ArrayList<>(100);
+
+ doTest(l);
+ }
+
+ public static void doTest(ArrayList<Object> l) throws Exception {
+ setupCallback();
+
+ enableAllocationTracking(null, true);
+
+ l.add(new Object());
+ l.add(new Integer(1));
+
+ enableAllocationTracking(null, false);
+
+ l.add(new Float(1.0f));
+
+ enableAllocationTracking(Thread.currentThread(), true);
+
+ l.add(new Short((short)0));
+
+ enableAllocationTracking(Thread.currentThread(), false);
+
+ l.add(new Byte((byte)0));
+
+ System.out.println("Tracking on same thread");
+
+ testThread(l, true, true);
+
+ l.add(new Byte((byte)0));
+
+ System.out.println("Tracking on same thread, not disabling tracking");
+
+ testThread(l, true, false);
+
+ System.out.println("Tracking on different thread");
+
+ testThread(l, false, true);
+
+ l.add(new Byte((byte)0));
+ }
+
+ private static void testThread(final ArrayList<Object> l, final boolean sameThread,
+ final boolean disableTracking) throws Exception {
+ final SimpleBarrier startBarrier = new SimpleBarrier(1);
+ final SimpleBarrier trackBarrier = new SimpleBarrier(1);
+ final SimpleBarrier disableBarrier = new SimpleBarrier(1);
+
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ startBarrier.dec();
+ trackBarrier.waitFor();
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ System.exit(1);
+ }
+
+ l.add(new Double(0.0));
+
+ if (disableTracking) {
+ enableAllocationTracking(sameThread ? this : Thread.currentThread(), false);
+ }
+ }
+ };
+
+ t.start();
+ startBarrier.waitFor();
+ enableAllocationTracking(sameThread ? t : Thread.currentThread(), true);
+ trackBarrier.dec();
+
+ t.join();
+ }
+
+ private static class SimpleBarrier {
+ int count;
+
+ public SimpleBarrier(int i) {
+ count = i;
+ }
+
+ public synchronized void dec() throws Exception {
+ count--;
+ notifyAll();
+ }
+
+ public synchronized void waitFor() throws Exception {
+ while (count != 0) {
+ wait();
+ }
+ }
+ }
+
+ private static native void setupCallback();
+ private static native void enableAllocationTracking(Thread thread, boolean enable);
+}
diff --git a/test/904-object-allocation/tracking.cc b/test/904-object-allocation/tracking.cc
new file mode 100644
index 0000000..c392cd4
--- /dev/null
+++ b/test/904-object-allocation/tracking.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 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 "tracking.h"
+
+#include <iostream>
+#include <pthread.h>
+#include <stdio.h>
+#include <vector>
+
+#include "base/logging.h"
+#include "jni.h"
+#include "openjdkjvmti/jvmti.h"
+#include "ScopedLocalRef.h"
+#include "ScopedUtfChars.h"
+#include "utils.h"
+
+namespace art {
+namespace Test904ObjectAllocation {
+
+static jvmtiEnv* jvmti_env;
+
+static std::string GetClassName(JNIEnv* jni_env, jclass cls) {
+ ScopedLocalRef<jclass> class_class(jni_env, jni_env->GetObjectClass(cls));
+ jmethodID mid = jni_env->GetMethodID(class_class.get(), "getName", "()Ljava/lang/String;");
+ ScopedLocalRef<jstring> str(
+ jni_env, reinterpret_cast<jstring>(jni_env->CallObjectMethod(cls, mid)));
+ ScopedUtfChars utf_chars(jni_env, str.get());
+ return utf_chars.c_str();
+}
+
+static void JNICALL ObjectAllocated(jvmtiEnv* ti_env ATTRIBUTE_UNUSED,
+ JNIEnv* jni_env,
+ jthread thread ATTRIBUTE_UNUSED,
+ jobject object,
+ jclass object_klass,
+ jlong size) {
+ std::string object_klass_descriptor = GetClassName(jni_env, object_klass);
+ ScopedLocalRef<jclass> object_klass2(jni_env, jni_env->GetObjectClass(object));
+ std::string object_klass_descriptor2 = GetClassName(jni_env, object_klass2.get());
+
+ printf("ObjectAllocated type %s/%s size %zu\n",
+ object_klass_descriptor.c_str(),
+ object_klass_descriptor2.c_str(),
+ static_cast<size_t>(size));
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_setupCallback(JNIEnv* env ATTRIBUTE_UNUSED, jclass) {
+ jvmtiEventCallbacks callbacks;
+ memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
+ callbacks.VMObjectAlloc = ObjectAllocated;
+
+ jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
+ if (ret != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(ret, &err);
+ printf("Error setting callbacks: %s\n", err);
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_enableAllocationTracking(JNIEnv* env ATTRIBUTE_UNUSED,
+ jclass,
+ jthread thread,
+ jboolean enable) {
+ jvmtiError ret = jvmti_env->SetEventNotificationMode(
+ enable ? JVMTI_ENABLE : JVMTI_DISABLE,
+ JVMTI_EVENT_VM_OBJECT_ALLOC,
+ thread);
+ if (ret != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(ret, &err);
+ printf("Error getting tag: %s\n", err);
+ }
+}
+
+// Don't do anything
+jint OnLoad(JavaVM* vm,
+ char* options ATTRIBUTE_UNUSED,
+ void* reserved ATTRIBUTE_UNUSED) {
+ if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
+ printf("Unable to get jvmti env!\n");
+ return 1;
+ }
+ return 0;
+}
+
+} // namespace Test904ObjectAllocation
+} // namespace art
+
diff --git a/test/904-object-allocation/tracking.h b/test/904-object-allocation/tracking.h
new file mode 100644
index 0000000..21c1837
--- /dev/null
+++ b/test/904-object-allocation/tracking.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_TEST_904_OBJECT_ALLOCATION_TRACKING_H_
+#define ART_TEST_904_OBJECT_ALLOCATION_TRACKING_H_
+
+#include <jni.h>
+
+namespace art {
+namespace Test904ObjectAllocation {
+
+jint OnLoad(JavaVM* vm, char* options, void* reserved);
+
+} // namespace Test904ObjectAllocation
+} // namespace art
+
+#endif // ART_TEST_904_OBJECT_ALLOCATION_TRACKING_H_