From dcfb3824562a5d75c8080686211584b1b40002b5 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Mon, 22 Feb 2016 16:56:54 -0800 Subject: [PATCH] Add regression test for alloc stack trace and unloading Test creates allocations in a different loader, then unloads it. This would free the ArtMethod except that we now visit them as roots. Bug: 26849503 (cherry picked from commit 8a7ef10d10ac1509b79d315fe865bd3c4731262b) Change-Id: If63e26b49380e7b99244ee25e70e729a1736344a --- test/130-hprof/src-ex/Allocator.java | 22 ++++++++++++ test/130-hprof/src/Main.java | 67 +++++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 test/130-hprof/src-ex/Allocator.java diff --git a/test/130-hprof/src-ex/Allocator.java b/test/130-hprof/src-ex/Allocator.java new file mode 100644 index 000000000..ee75a14f3 --- /dev/null +++ b/test/130-hprof/src-ex/Allocator.java @@ -0,0 +1,22 @@ +/* + * 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. + */ + +// Simple allocator that returns a boot class path object. +public class Allocator { + public static Object allocObject() { + return new Object(); + } +} diff --git a/test/130-hprof/src/Main.java b/test/130-hprof/src/Main.java index 67e52323d..9868c617f 100644 --- a/test/130-hprof/src/Main.java +++ b/test/130-hprof/src/Main.java @@ -16,6 +16,7 @@ import java.io.File; import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; @@ -34,24 +35,21 @@ public class Main { } } - public static void main(String[] args) { - // Create some data. - Object data[] = new Object[TEST_LENGTH]; - for (int i = 0; i < data.length; i++) { - if (makeArray(i)) { - data[i] = new Object[TEST_LENGTH]; - } else { - data[i] = String.valueOf(i); - } + private static Object allocInDifferentLoader() throws Exception { + final String DEX_FILE = System.getenv("DEX_LOCATION") + "/130-hprof-ex.jar"; + Class pathClassLoader = Class.forName("dalvik.system.PathClassLoader"); + if (pathClassLoader == null) { + throw new AssertionError("Couldn't find path class loader class"); } - for (int i = 0; i < data.length; i++) { - if (makeArray(i)) { - Object data2[] = (Object[]) data[i]; - fillArray(data, data2, i); - } - } - System.out.println("Generated data."); + Constructor constructor = + pathClassLoader.getDeclaredConstructor(String.class, ClassLoader.class); + ClassLoader loader = (ClassLoader)constructor.newInstance( + DEX_FILE, ClassLoader.getSystemClassLoader()); + Class allocator = loader.loadClass("Allocator"); + return allocator.getDeclaredMethod("allocObject", null).invoke(null); + } + private static void createDumpAndConv() throws RuntimeException { File dumpFile = null; File convFile = null; @@ -88,6 +86,43 @@ public class Main { } } + public static void main(String[] args) throws Exception { + // Create some data. + Object data[] = new Object[TEST_LENGTH]; + for (int i = 0; i < data.length; i++) { + if (makeArray(i)) { + data[i] = new Object[TEST_LENGTH]; + } else { + data[i] = String.valueOf(i); + } + } + for (int i = 0; i < data.length; i++) { + if (makeArray(i)) { + Object data2[] = (Object[]) data[i]; + fillArray(data, data2, i); + } + } + System.out.println("Generated data."); + + createDumpAndConv(); + Class klass = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal"); + if (klass == null) { + throw new AssertionError("Couldn't find path class loader class"); + } + Method enableMethod = klass.getDeclaredMethod("enableRecentAllocations", + Boolean.TYPE); + if (enableMethod == null) { + throw new AssertionError("Couldn't find path class loader class"); + } + enableMethod.invoke(null, true); + Object o = allocInDifferentLoader(); + // Run GC to cause class unloading. + Runtime.getRuntime().gc(); + createDumpAndConv(); + // TODO: Somehow check contents of hprof file. + enableMethod.invoke(null, false); + } + private static File getHprofConf() { // Use the java.library.path. It points to the lib directory. File libDir = new File(System.getProperty("java.library.path")); -- 2.11.0