diff options
-rw-r--r-- | test/2040-huge-native-alloc/Android.bp | 40 | ||||
-rw-r--r-- | test/2040-huge-native-alloc/expected-stderr.txt | 0 | ||||
-rw-r--r-- | test/2040-huge-native-alloc/expected-stdout.txt | 3 | ||||
-rw-r--r-- | test/2040-huge-native-alloc/huge_native_buf.cc | 38 | ||||
-rw-r--r-- | test/2040-huge-native-alloc/info.txt | 2 | ||||
-rw-r--r-- | test/2040-huge-native-alloc/src/Main.java | 99 | ||||
-rw-r--r-- | test/Android.bp | 1 | ||||
-rw-r--r-- | test/knownfailures.json | 3 |
8 files changed, 185 insertions, 1 deletions
diff --git a/test/2040-huge-native-alloc/Android.bp b/test/2040-huge-native-alloc/Android.bp new file mode 100644 index 0000000000..8a5501d853 --- /dev/null +++ b/test/2040-huge-native-alloc/Android.bp @@ -0,0 +1,40 @@ +// Generated by `regen-test-files`. Do not edit manually. + +// Build rules for ART run-test `2040-huge-native-alloc`. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "art_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["art_license"], +} + +// Test's Dex code. +java_test { + name: "art-run-test-2040-huge-native-alloc", + defaults: ["art-run-test-defaults"], + test_config_template: ":art-run-test-target-no-test-suite-tag-template", + srcs: ["src/**/*.java"], + data: [ + ":art-run-test-2040-huge-native-alloc-expected-stdout", + ":art-run-test-2040-huge-native-alloc-expected-stderr", + ], +} + +// Test's expected standard output. +genrule { + name: "art-run-test-2040-huge-native-alloc-expected-stdout", + out: ["art-run-test-2040-huge-native-alloc-expected-stdout.txt"], + srcs: ["expected-stdout.txt"], + cmd: "cp -f $(in) $(out)", +} + +// Test's expected standard error. +genrule { + name: "art-run-test-2040-huge-native-alloc-expected-stderr", + out: ["art-run-test-2040-huge-native-alloc-expected-stderr.txt"], + srcs: ["expected-stderr.txt"], + cmd: "cp -f $(in) $(out)", +} diff --git a/test/2040-huge-native-alloc/expected-stderr.txt b/test/2040-huge-native-alloc/expected-stderr.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2040-huge-native-alloc/expected-stderr.txt diff --git a/test/2040-huge-native-alloc/expected-stdout.txt b/test/2040-huge-native-alloc/expected-stdout.txt new file mode 100644 index 0000000000..f2fc51cbf2 --- /dev/null +++ b/test/2040-huge-native-alloc/expected-stdout.txt @@ -0,0 +1,3 @@ +JNI_OnLoad called +Main Started +Main Finished diff --git a/test/2040-huge-native-alloc/huge_native_buf.cc b/test/2040-huge-native-alloc/huge_native_buf.cc new file mode 100644 index 0000000000..06186c9371 --- /dev/null +++ b/test/2040-huge-native-alloc/huge_native_buf.cc @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 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 "base/utils.h" +#include "jni.h" +#include <stddef.h> + +namespace art { + +static constexpr size_t HUGE_SIZE = 10'000'000; + +extern "C" JNIEXPORT jobject JNICALL Java_Main_getHugeNativeBuffer( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) { + char* buffer = new char[HUGE_SIZE]; + return env->NewDirectByteBuffer(buffer, HUGE_SIZE); +} + +extern "C" JNIEXPORT void JNICALL Java_Main_deleteHugeNativeBuffer( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject jbuffer) { + delete [] static_cast<char*>(env->GetDirectBufferAddress(jbuffer)); +} + +} // namespace art + + diff --git a/test/2040-huge-native-alloc/info.txt b/test/2040-huge-native-alloc/info.txt new file mode 100644 index 0000000000..41c5ef60b4 --- /dev/null +++ b/test/2040-huge-native-alloc/info.txt @@ -0,0 +1,2 @@ +Check that we properly trigger world stop collections after a lot of native +allocation. diff --git a/test/2040-huge-native-alloc/src/Main.java b/test/2040-huge-native-alloc/src/Main.java new file mode 100644 index 0000000000..0366e5e7d1 --- /dev/null +++ b/test/2040-huge-native-alloc/src/Main.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2021 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 dalvik.system.VMRuntime; +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; + +public class Main { + + static final int HOW_MANY_HUGE = 110; // > 1GB to trigger blocking in default config. + int allocated = 0; + int deallocated = 0; + static Object lock = new Object(); + WeakReference<BufferHolder>[] references = new WeakReference[HOW_MANY_HUGE]; + + class BufferHolder { + private ByteBuffer buffer; + BufferHolder() { + ++allocated; + buffer = getHugeNativeBuffer(); + } + protected void finalize() { + synchronized(lock) { + ++deallocated; + } + deleteHugeNativeBuffer(buffer); + buffer = null; + } + } + + // Repeatedly inform the GC of native allocations. Return the time (in nsecs) this takes. + private static long timeNotifications() { + VMRuntime vmr = VMRuntime.getRuntime(); + long startNanos = System.nanoTime(); + // Iteration count must be >= Heap::kNotifyNativeInterval. + for (int i = 0; i < 400; ++i) { + vmr.notifyNativeAllocation(); + } + return System.nanoTime() - startNanos; + } + + public static void main(String[] args) { + System.loadLibrary(args[0]); + System.out.println("Main Started"); + new Main().run(); + System.out.println("Main Finished"); + } + + void run() { + timeNotifications(); // warm up. + long referenceTime1 = timeNotifications(); + long referenceTime2 = timeNotifications(); + long referenceTime = Math.min(referenceTime1, referenceTime2); + + // Allocate half a GB of native memory without informing the GC. + for (int i = 0; i < HOW_MANY_HUGE; ++i) { + new BufferHolder(); + } + + // One of the notifications should block for GC to catch up. + long actualTime = timeNotifications(); + + if (actualTime > 500_000_000) { + System.out.println("Notifications ran too slowly; excessive blocking? msec = " + + (actualTime / 1_000_000)); + } else if (actualTime < 3 * referenceTime + 2_000_000) { + System.out.println("Notifications ran too quickly; no blocking GC? msec = " + + (actualTime / 1_000_000)); + } + + // Let finalizers run. + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + System.out.println("Unexpected interrupt"); + } + + if (deallocated > allocated || deallocated < allocated - 5 /* slop for register references */) { + System.out.println("Unexpected number of deallocated objects:"); + System.out.println("Allocated = " + allocated + " deallocated = " + deallocated); + } + } + + private static native ByteBuffer getHugeNativeBuffer(); + private static native void deleteHugeNativeBuffer(ByteBuffer buf); +} diff --git a/test/Android.bp b/test/Android.bp index e710509bd9..e393f06a3b 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -730,6 +730,7 @@ cc_defaults { "2033-shutdown-mechanics/native_shutdown.cc", "2036-jni-filechannel/jni_filechannel.cc", "2037-thread-name-inherit/thread_name_inherit.cc", + "2040-huge-native-alloc/huge_native_buf.cc", "common/runtime_state.cc", "common/stack_inspect.cc", ], diff --git a/test/knownfailures.json b/test/knownfailures.json index d9b089d17a..10da9ab062 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -1190,7 +1190,8 @@ "2033-shutdown-mechanics", "2035-structural-native-method", "2036-structural-subclass-shadow", - "2038-hiddenapi-jvmti-ext"], + "2038-hiddenapi-jvmti-ext", + "2040-huge-native-alloc"], "variant": "jvm", "description": ["Doesn't run on RI."] }, |