diff options
author | 2017-10-05 17:07:40 -0700 | |
---|---|---|
committer | 2017-10-06 15:51:29 +0000 | |
commit | abbc4bc8a6716a6e524ec2572834fa34604519c1 (patch) | |
tree | d2f4bf7796f73f1c6717b1de3c954ad85cd4b256 | |
parent | 97785f595a8a3b5c766021a07c47a2ca81e4a810 (diff) |
Don't notify jit of non-invokable methods being redefined.
This can lead to crashes if the method stored something in it's data_
pointer (such as it's single-implementation).
Bug: 67465851
Test: ./test.py --host -j50
Change-Id: Iee060560f558a91c70e3c72b739de8292ba5a43b
-rw-r--r-- | openjdkjvmti/ti_redefine.cc | 4 | ||||
-rw-r--r-- | test/1938-transform-abstract-single-impl/expected.txt | 4 | ||||
-rw-r--r-- | test/1938-transform-abstract-single-impl/info.txt | 2 | ||||
-rwxr-xr-x | test/1938-transform-abstract-single-impl/run | 17 | ||||
-rw-r--r-- | test/1938-transform-abstract-single-impl/src/Main.java | 100 | ||||
-rw-r--r-- | test/1938-transform-abstract-single-impl/src/art/Redefinition.java | 91 |
6 files changed, 217 insertions, 1 deletions
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 5d9bf2ce6e..a90f4173f6 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -1399,7 +1399,9 @@ void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> method.SetNotIntrinsic(); // Notify the jit that this method is redefined. art::jit::Jit* jit = driver_->runtime_->GetJit(); - if (jit != nullptr) { + // Non-invokable methods don't have any JIT data associated with them so we don't need to tell + // the jit about them. + if (jit != nullptr && method.IsInvokable()) { jit->GetCodeCache()->NotifyMethodRedefined(&method); } } diff --git a/test/1938-transform-abstract-single-impl/expected.txt b/test/1938-transform-abstract-single-impl/expected.txt new file mode 100644 index 0000000000..6a06f9baab --- /dev/null +++ b/test/1938-transform-abstract-single-impl/expected.txt @@ -0,0 +1,4 @@ +JNI_OnLoad called +Running sayHi() - hello +redefining TransformAbstract +Running sayHi() - Goodbye diff --git a/test/1938-transform-abstract-single-impl/info.txt b/test/1938-transform-abstract-single-impl/info.txt new file mode 100644 index 0000000000..5df8306981 --- /dev/null +++ b/test/1938-transform-abstract-single-impl/info.txt @@ -0,0 +1,2 @@ +Tests that single-implementation abstract methods don't crash the runtime when +their declaring class is redefined. diff --git a/test/1938-transform-abstract-single-impl/run b/test/1938-transform-abstract-single-impl/run new file mode 100755 index 0000000000..adb1a1c507 --- /dev/null +++ b/test/1938-transform-abstract-single-impl/run @@ -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-run "$@" --jvmti --no-app-image diff --git a/test/1938-transform-abstract-single-impl/src/Main.java b/test/1938-transform-abstract-single-impl/src/Main.java new file mode 100644 index 0000000000..7ac2172eb4 --- /dev/null +++ b/test/1938-transform-abstract-single-impl/src/Main.java @@ -0,0 +1,100 @@ +/* + * 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. + */ + +import art.Redefinition; +import java.util.Base64; +public class Main { + static abstract class TransformAbstract { + public abstract void doSayHi(); + + public void sayHi() { + System.out.println("hello"); + } + } + + static final class TransformConcrete extends TransformAbstract { + public final void doSayHi() { + System.out.print("Running sayHi() - "); + sayHi(); + } + } + + public static native void ensureJitCompiled(Class k, String m); + + /** + * base64 encoded class/dex file for + * static abstract class TransformAbstract { + * public abstract void doSayHi(); + * public void sayHi() { + * System.out.println("Goodbye"); + * } + * } + */ + private static final byte[] CLASS_BYTES = Base64.getDecoder().decode( + "yv66vgAAADQAIQoABgAPCQAQABEIABIKABMAFAcAFgcAGQEABjxpbml0PgEAAygpVgEABENvZGUB" + + "AA9MaW5lTnVtYmVyVGFibGUBAAdkb1NheUhpAQAFc2F5SGkBAApTb3VyY2VGaWxlAQAJTWFpbi5q" + + "YXZhDAAHAAgHABoMABsAHAEAB0dvb2RieWUHAB0MAB4AHwcAIAEAFk1haW4kVHJhbnNmb3JtQWJz" + + "dHJhY3QBABFUcmFuc2Zvcm1BYnN0cmFjdAEADElubmVyQ2xhc3NlcwEAEGphdmEvbGFuZy9PYmpl" + + "Y3QBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2" + + "YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAARNYWlu" + + "BCAABQAGAAAAAAADAAAABwAIAAEACQAAAB0AAQABAAAABSq3AAGxAAAAAQAKAAAABgABAAAAHAQB" + + "AAsACAAAAAEADAAIAAEACQAAACUAAgABAAAACbIAAhIDtgAEsQAAAAEACgAAAAoAAgAAAB8ACAAg" + + "AAIADQAAAAIADgAYAAAACgABAAUAFQAXBAg="); + private static final byte[] DEX_BYTES = Base64.getDecoder().decode( + "ZGV4CjAzNQCQkoTiKzIz0l96rtsnUxdY4Kwx+YINWFHEAwAAcAAAAHhWNBIAAAAAAAAAAAADAAAV" + + "AAAAcAAAAAkAAADEAAAAAgAAAOgAAAABAAAAAAEAAAUAAAAIAQAAAQAAADABAAB0AgAAUAEAAKoB" + + "AACyAQAAuwEAANUBAADdAQAAAQIAACECAAA4AgAATAIAAGACAAB0AgAAfwIAAJICAACVAgAAmQIA" + + "AKYCAACvAgAAtQIAALoCAADDAgAAygIAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAA" + + "DAAAAAwAAAAIAAAAAAAAAA0AAAAIAAAApAEAAAcABAARAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAT" + + "AAAABAABABIAAAAFAAAAAAAAAAAAAAAABAAABQAAAAAAAAAKAAAAlAEAAOwCAAAAAAAAAgAAANwC" + + "AADiAgAAAQABAAEAAADRAgAABAAAAHAQBAAAAA4AAwABAAIAAADWAgAACAAAAGIAAAAaAQEAbiAD" + + "ABAADgBQAQAAAAAAAAAAAAAAAAAAAQAAAAYABjxpbml0PgAHR29vZGJ5ZQAYTE1haW4kVHJhbnNm" + + "b3JtQWJzdHJhY3Q7AAZMTWFpbjsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsA" + + "HkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJM" + + "amF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07" + + "AAlNYWluLmphdmEAEVRyYW5zZm9ybUFic3RyYWN0AAFWAAJWTAALYWNjZXNzRmxhZ3MAB2RvU2F5" + + "SGkABG5hbWUAA291dAAHcHJpbnRsbgAFc2F5SGkABXZhbHVlABwABw4AHwAHDngAAgIBFBgBAgMC" + + "DiQIBBAXCwAAAQIAgIAE3AIBgQgAAQH0AgAAEAAAAAAAAAABAAAAAAAAAAEAAAAVAAAAcAAAAAIA" + + "AAAJAAAAxAAAAAMAAAACAAAA6AAAAAQAAAABAAAAAAEAAAUAAAAFAAAACAEAAAYAAAABAAAAMAEA" + + "AAMQAAABAAAAUAEAAAEgAAACAAAAXAEAAAYgAAABAAAAlAEAAAEQAAABAAAApAEAAAIgAAAVAAAA" + + "qgEAAAMgAAACAAAA0QIAAAQgAAACAAAA3AIAAAAgAAABAAAA7AIAAAAQAAABAAAAAAMAAA=="); + + public static void main(String[] args) throws Exception { + System.loadLibrary(args[0]); + Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); + + ensureJitCompiled(TransformAbstract.class, "sayHi"); + ensureJitCompiled(TransformConcrete.class, "doSayHi"); + + TransformAbstract t1 = new TransformConcrete(); + t1.doSayHi(); + + assertSingleImplementation(TransformAbstract.class, "doSayHi", true); + + System.out.println("redefining TransformAbstract"); + Redefinition.doCommonClassRedefinition(TransformAbstract.class, CLASS_BYTES, DEX_BYTES); + + t1.doSayHi(); + } + + private static native boolean hasSingleImplementation(Class<?> clazz, String method_name); + private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) { + if (hasSingleImplementation(clazz, method_name) != b) { + System.out.println(clazz + "." + method_name + + " doesn't have single implementation value of " + b); + } + } +} diff --git a/test/1938-transform-abstract-single-impl/src/art/Redefinition.java b/test/1938-transform-abstract-single-impl/src/art/Redefinition.java new file mode 100644 index 0000000000..56d2938a01 --- /dev/null +++ b/test/1938-transform-abstract-single-impl/src/art/Redefinition.java @@ -0,0 +1,91 @@ +/* + * 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); +} |