diff options
| author | 2024-09-19 13:03:28 +0100 | |
|---|---|---|
| committer | 2024-09-23 09:21:07 +0000 | |
| commit | 56d62450fcd69434b94158a42f1a195bd7ee858b (patch) | |
| tree | e629e304607c1f3cc185f5b7328872b06ad466e6 /test/2281-method-handle-invoke-static-class-unload/src-art/Main.java | |
| parent | e5d19588b1b3163193f867e7ddb6cd6d19658841 (diff) | |
Store reference to the target class in MH object.
Previously MH object only stored pointer to ArtField / ArtMethod
and GC could unload target class.
Bug: 366474683
Test: ./art/test/testrunner/testrunner.py --host --64 -b
Test: ./art/test/testrunner/testrunner.py --host --64 --jvm -b -t 2281-method
Test: ./art/test.py --host -g
Change-Id: I6e91fc59da7c55c15ed55fadaf796050eebb0f5e
Diffstat (limited to 'test/2281-method-handle-invoke-static-class-unload/src-art/Main.java')
| -rw-r--r-- | test/2281-method-handle-invoke-static-class-unload/src-art/Main.java | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/test/2281-method-handle-invoke-static-class-unload/src-art/Main.java b/test/2281-method-handle-invoke-static-class-unload/src-art/Main.java new file mode 100644 index 0000000000..8e03fe04bf --- /dev/null +++ b/test/2281-method-handle-invoke-static-class-unload/src-art/Main.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2024 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.InMemoryDexClassLoader; + +import static java.lang.invoke.MethodType.methodType; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.util.Base64; +import java.util.List; +import java.util.function.Consumer; + +public class Main { + // src-ex/ClassWithAMethod.java + private static final String DEX_FILE = + "ZGV4CjA0MQC4x9/g6TtIcd5240Zevdlr1D/wRBHV4Tv0BAAAeAAAAHhWNBIAAAAAAAAAADAEAAAW" + + "AAAAeAAAAAcAAADQAAAABAAAAOwAAAAAAAAAAAAAAAcAAAAcAQAAAQAAAFQBAAAAAAAAAAAAAPQE" + + "AAAAAAAAGgIAAB8CAAAnAgAAOQIAAFACAABTAgAAVgIAAGoCAACOAgAAqgIAAL4CAADfAgAA4gIA" + + "AOYCAAD5AgAABQMAABgDAAAeAwAAJgMAADQDAAA7AwAASAMAAAQAAAAGAAAABwAAAAgAAAAJAAAA" + + "CgAAAAsAAAAEAAAAAAAAAAAAAAAFAAAABQAAAAAAAAALAAAABgAAAAAAAAAMAAAABgAAABQCAAAB" + + "AAIAAQAAAAEAAQANAAAAAQAAABEAAAABAAEAEgAAAAEAAgAUAAAAAwADAAEAAAAEAAIAAQAAAAEA" + + "AAABAAAABAAAAAAAAAADAAAAGAQAAPYDAAAAAAAABAAAAAIAAAABAAAAAAAAAPwBAAACAAAAEhAP" + + "AAEAAAAAAAAAAAIAAAMAAAD+AAAAEQAAAAEAAAAAAAAABAIAAAUAAABxAAQAAAASABEAAAABAAEA" + + "AQAAAAkCAAAEAAAAcBAGAAAADgACAAAAAgAAAA0CAAAIAAAAIgADABoBFABwIAUAEAAnABoADgAs" + + "AA4AJwAOPAAYAA4AHgAOAAAAAAEAAAAEAAMoKUkABjxpbml0PgAQQ2xhc3NXaXRoQU1ldGhvZAAV" + + "Q2xhc3NXaXRoQU1ldGhvZC5qYXZhAAFJAAFMABJMQ2xhc3NXaXRoQU1ldGhvZDsAIkxhbm5vdGF0" + + "aW9ucy9Db25zdGFudE1ldGhvZEhhbmRsZTsAGkxqYXZhL2xhbmcvQXNzZXJ0aW9uRXJyb3I7ABJM" + + "amF2YS9sYW5nL09iamVjdDsAH0xqYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZTsAAVYAAlZM" + + "ABFjb25zdE1ldGhvZEhhbmRsZQAKZGVzY3JpcHRvcgARZmllbGRPck1ldGhvZE5hbWUABGtpbmQA" + + "Bm1ldGhvZAAMbWV0aG9kSGFuZGxlAAVvd25lcgALdW5yZWFjaGFibGUAnAF+fkQ4eyJiYWNrZW5k" + + "IjoiZGV4IiwiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwiaGFzLWNoZWNrc3VtcyI6ZmFsc2Us" + + "Im1pbi1hcGkiOjI4LCJzaGEtMSI6IjdkZTM3N2E4MGI1MzQ1MGY1Y2ExYTNmYzUwZjZkYzk5M2U3" + + "ZThhM2UiLCJ2ZXJzaW9uIjoiOC44LjQtZGV2In0AAQIEDhcADxcREAQEExcCAAAFAACBgATEAwEJ" + + "kAMBCfwCAQqoAwEK3AMBAAAA5wMAAAAAAAAAAAAAAQAAAAAAAAADAAAAEAQAABAAAAAAAAAAAQAA" + + "AAAAAAABAAAAFgAAAHgAAAACAAAABwAAANAAAAADAAAABAAAAOwAAAAFAAAABwAAABwBAAAGAAAA" + + "AQAAAFQBAAAIAAAAAQAAAHQBAAABIAAABQAAAHwBAAADIAAABQAAAPwBAAABEAAAAQAAABQCAAAC" + + "IAAAFgAAABoCAAAEIAAAAQAAAOcDAAAAIAAAAQAAAPYDAAADEAAAAQAAABAEAAAGIAAAAQAAABgE" + + "AAAAEAAAAQAAADAEAAA="; + + private static final int ITERATIONS = 5; + + public static void main(String[] args) throws Throwable { + verify($noinline$getJavaApiMethodHandle()); + verify($noinline$getConstMethodHandle()); + } + + private static void verify(MethodHandle mh) { + int result = 0; + for (int i = 0; i < ITERATIONS; ++i) { + try { + result += (int) mh.invokeWithArguments(List.of()); + } catch (Throwable t) { + throw new RuntimeException(t); + } + Runtime.getRuntime().gc(); + System.runFinalization(); + } + + if (result != ITERATIONS) { + throw new AssertionError(); + } + } + + private static MethodHandle $noinline$getJavaApiMethodHandle() throws Throwable { + ClassLoader loader = new InMemoryDexClassLoader( + ByteBuffer.wrap(Base64.getDecoder().decode(DEX_FILE)), + ClassLoader.getSystemClassLoader()); + Class<?> clazz = loader.loadClass("ClassWithAMethod"); + return MethodHandles.publicLookup().findStatic(clazz, "method", methodType(int.class)); + } + + private static MethodHandle $noinline$getConstMethodHandle() throws Throwable { + ClassLoader loader = new InMemoryDexClassLoader( + ByteBuffer.wrap(Base64.getDecoder().decode(DEX_FILE)), + ClassLoader.getSystemClassLoader()); + Class<?> clazz = loader.loadClass("ClassWithAMethod"); + + return (MethodHandle) clazz.getDeclaredMethod("constMethodHandle").invoke(null); + } +}
\ No newline at end of file |