diff options
18 files changed, 416 insertions, 16 deletions
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index c505933853..dccc226f60 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -1131,10 +1131,6 @@ bool Redefiner::ClassRedefinition::CheckRedefinable() { jvmtiError res; if (driver_->type_ == RedefinitionType::kStructural && this->IsStructuralRedefinition()) { res = Redefiner::GetClassRedefinitionError<RedefinitionType::kStructural>(h_klass, &err); - if (res == OK && HasVirtualMembers() && h_klass->IsFinalizable()) { - res = ERR(INTERNAL); - err = "Cannot redefine finalizable objects at this time."; - } } else { res = Redefiner::GetClassRedefinitionError<RedefinitionType::kNormal>(h_klass, &err); } @@ -1750,7 +1746,21 @@ bool Redefiner::ClassRedefinition::CollectAndCreateNewInstances( [&](auto class_pair) REQUIRES_SHARED(art::Locks::mutator_lock_) { return class_pair.first == hinstance->GetClass(); })); - art::ObjPtr<art::mirror::Object> new_instance(new_type->AllocObject(driver_->self_)); + // Make sure when allocating the new instance we don't add it's finalizer since we will directly + // replace the old object in the finalizer reference. If we added it here to we would call + // finalize twice. + // NB If a type is changed from being non-finalizable to finalizable the finalizers on any + // objects created before the redefine will never be called. This is (sort of) allowable by + // the spec and greatly simplifies implementation. + // TODO Make it so we will always call all finalizers, even if the object when it was created + // wasn't finalizable. To do this we need to be careful of handling failure correctly and making + // sure that objects aren't finalized multiple times and that instances of failed redefinitions + // aren't finalized. + art::ObjPtr<art::mirror::Object> new_instance( + new_type->Alloc</*kIsInstrumented=*/true, + art::mirror::Class::AddFinalizer::kNoAddFinalizer, + /*kCheckAddFinalizer=*/false>( + driver_->self_, driver_->runtime_->GetHeap()->GetCurrentAllocator())); if (new_instance.IsNull()) { driver_->self_->AssertPendingOOMException(); driver_->self_->ClearException(); diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 338928ec16..1e422014dd 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -199,14 +199,15 @@ inline ObjPtr<mirror::Object> AllocObjectFromCodeResolved(ObjPtr<mirror::Class> return nullptr; } gc::Heap* heap = Runtime::Current()->GetHeap(); - // Pass in false since the object cannot be finalizable. + // Pass in kNoAddFinalizer since the object cannot be finalizable. // CheckClassInitializedForObjectAlloc can cause thread suspension which means we may now be // instrumented. - return klass->Alloc</*kInstrumented=*/true, /*kCheckAddFinalizer=*/false>( + return klass->Alloc</*kInstrumented=*/true, mirror::Class::AddFinalizer::kNoAddFinalizer>( self, heap->GetCurrentAllocator()); } - // Pass in false since the object cannot be finalizable. - return klass->Alloc<kInstrumented, /*kCheckAddFinalizer=*/false>(self, allocator_type); + // Pass in kNoAddFinalizer since the object cannot be finalizable. + return klass->Alloc<kInstrumented, + mirror::Class::AddFinalizer::kNoAddFinalizer>(self, allocator_type); } // Given the context of a calling Method and an initialized class, create an instance. @@ -216,8 +217,9 @@ inline ObjPtr<mirror::Object> AllocObjectFromCodeInitialized(ObjPtr<mirror::Clas Thread* self, gc::AllocatorType allocator_type) { DCHECK(klass != nullptr); - // Pass in false since the object cannot be finalizable. - return klass->Alloc<kInstrumented, /*kCheckAddFinalizer=*/false>(self, allocator_type); + // Pass in kNoAddFinalizer since the object cannot be finalizable. + return klass->Alloc<kInstrumented, + mirror::Class::AddFinalizer::kNoAddFinalizer>(self, allocator_type); } diff --git a/runtime/mirror/class-alloc-inl.h b/runtime/mirror/class-alloc-inl.h index 28612443be..5627b4956e 100644 --- a/runtime/mirror/class-alloc-inl.h +++ b/runtime/mirror/class-alloc-inl.h @@ -46,13 +46,19 @@ inline void Class::CheckObjectAlloc() { DCHECK_GE(this->object_size_, sizeof(Object)); } -template<bool kIsInstrumented, bool kCheckAddFinalizer> +template<bool kIsInstrumented, Class::AddFinalizer kAddFinalizer, bool kCheckAddFinalizer> inline ObjPtr<Object> Class::Alloc(Thread* self, gc::AllocatorType allocator_type) { CheckObjectAlloc(); gc::Heap* heap = Runtime::Current()->GetHeap(); - const bool add_finalizer = kCheckAddFinalizer && IsFinalizable(); - if (!kCheckAddFinalizer) { - DCHECK(!IsFinalizable()); + bool add_finalizer; + switch (kAddFinalizer) { + case Class::AddFinalizer::kUseClassTag: + add_finalizer = IsFinalizable(); + break; + case Class::AddFinalizer::kNoAddFinalizer: + add_finalizer = false; + DCHECK(!kCheckAddFinalizer || !IsFinalizable()); + break; } // Note that the `this` pointer may be invalidated after the allocation. ObjPtr<Object> obj = diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index b600c43fe3..3e24346bf3 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -498,8 +498,21 @@ class MANAGED Class final : public Object { template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsPrimitiveArray() REQUIRES_SHARED(Locks::mutator_lock_); + // Enum used to control whether we try to add a finalizer-reference for object alloc or not. + enum class AddFinalizer { + // Don't create a finalizer reference regardless of what the class-flags say. + kNoAddFinalizer, + // Use the class-flags to figure out if we should make a finalizer reference. + kUseClassTag, + }; + // Creates a raw object instance but does not invoke the default constructor. - template<bool kIsInstrumented = true, bool kCheckAddFinalizer = true> + // kCheckAddFinalizer controls whether we use a DCHECK to sanity check that we create a + // finalizer-reference if needed. This should only be disabled when doing structural class + // redefinition. + template <bool kIsInstrumented = true, + AddFinalizer kAddFinalizer = AddFinalizer::kUseClassTag, + bool kCheckAddFinalizer = true> ALWAYS_INLINE ObjPtr<Object> Alloc(Thread* self, gc::AllocatorType allocator_type) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); diff --git a/test/2006-virtual-structural-finalizing/expected.txt b/test/2006-virtual-structural-finalizing/expected.txt new file mode 100644 index 0000000000..e9653575c1 --- /dev/null +++ b/test/2006-virtual-structural-finalizing/expected.txt @@ -0,0 +1,3 @@ +Finalizing +start_counter: 1 +Finish_counter: 1 diff --git a/test/2006-virtual-structural-finalizing/info.txt b/test/2006-virtual-structural-finalizing/info.txt new file mode 100644 index 0000000000..3e5291df87 --- /dev/null +++ b/test/2006-virtual-structural-finalizing/info.txt @@ -0,0 +1,4 @@ +Tests structural redefinition with multiple threads. + +Tests that using the structural redefinition while concurrently loading and using a subtype of +the class being redefined doesn't cause any unexpected problems. diff --git a/test/2006-virtual-structural-finalizing/run b/test/2006-virtual-structural-finalizing/run new file mode 100755 index 0000000000..03e41a58e7 --- /dev/null +++ b/test/2006-virtual-structural-finalizing/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 --runtime-option -Xopaque-jni-ids:true diff --git a/test/2006-virtual-structural-finalizing/src-art/Main.java b/test/2006-virtual-structural-finalizing/src-art/Main.java new file mode 100644 index 0000000000..11f9aa7e1e --- /dev/null +++ b/test/2006-virtual-structural-finalizing/src-art/Main.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 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. + */ + +public class Main { + public static void main(String[] args) throws Exception { + art.Test2006.run(); + } +} diff --git a/test/2006-virtual-structural-finalizing/src-art/art/Redefinition.java b/test/2006-virtual-structural-finalizing/src-art/art/Redefinition.java new file mode 120000 index 0000000000..81eaf31bbb --- /dev/null +++ b/test/2006-virtual-structural-finalizing/src-art/art/Redefinition.java @@ -0,0 +1 @@ +../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/2006-virtual-structural-finalizing/src-art/art/Test2006.java b/test/2006-virtual-structural-finalizing/src-art/art/Test2006.java new file mode 100644 index 0000000000..510d13dc41 --- /dev/null +++ b/test/2006-virtual-structural-finalizing/src-art/art/Test2006.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 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 dalvik.system.InMemoryDexClassLoader; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Base64; +import java.util.concurrent.CountDownLatch; +import java.util.function.Supplier; +import java.util.concurrent.atomic.*; +import java.lang.ref.*; + +public class Test2006 { + public static final CountDownLatch start_latch = new CountDownLatch(1); + public static final CountDownLatch redefine_latch = new CountDownLatch(1); + public static final CountDownLatch finish_latch = new CountDownLatch(1); + public static volatile int start_counter = 0; + public static volatile int finish_counter = 0; + public static class Transform { + public Transform() { } + protected void finalize() throws Throwable { + System.out.println("Finalizing"); + start_counter++; + start_latch.countDown(); + redefine_latch.await(); + finish_counter++; + finish_latch.countDown(); + } + } + + /** + * base64 encoded class/dex file for + * public static class Transform { + * public String greeting; + * + * public Transform() { + * greeting = "Hello"; + * } + * protected void finalize() { + * System.out.println("NOTHING HERE!"); + * } + * } + */ + private static final byte[] DEX_BYTES = + Base64.getDecoder() + .decode( +"ZGV4CjAzNQDtxu0Tsy2rLn9iTZHx3r+yuY0IuN+y1el4BAAAcAAAAHhWNBIAAAAAAAAAALQDAAAX" + +"AAAAcAAAAAkAAADMAAAAAgAAAPAAAAACAAAACAEAAAQAAAAYAQAAAQAAADgBAAAgAwAAWAEAAKoB" + +"AACyAQAAuQEAANMBAADjAQAABwIAACcCAAA+AgAAUgIAAGYCAAB6AgAAiQIAAJgCAACjAgAApgIA" + +"AKoCAAC3AgAAwQIAAMsCAADRAgAA1gIAAN8CAADmAgAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAA" + +"CAAAAAkAAAANAAAADQAAAAgAAAAAAAAADgAAAAgAAACkAQAAAAAGABEAAAAHAAQAEwAAAAAAAAAA" + +"AAAAAAAAABAAAAAEAAEAFAAAAAUAAAAAAAAAAAAAAAEAAAAFAAAAAAAAAAsAAACkAwAAhAMAAAAA" + +"AAACAAEAAQAAAJgBAAAIAAAAcBADAAEAGgABAFsQAAAOAAMAAQACAAAAngEAAAgAAABiAAEAGgEK" + +"AG4gAgAQAA4ABgAOPEsACgAOeAAAAQAAAAYABjxpbml0PgAFSGVsbG8AGExhcnQvVGVzdDIwMDYk" + +"VHJhbnNmb3JtOwAOTGFydC9UZXN0MjAwNjsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdD" + +"bGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAVTGphdmEvaW8vUHJpbnRTdHJl" + +"YW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9T" + +"eXN0ZW07AA1OT1RISU5HIEhFUkUhAA1UZXN0MjAwNi5qYXZhAAlUcmFuc2Zvcm0AAVYAAlZMAAth" + +"Y2Nlc3NGbGFncwAIZmluYWxpemUACGdyZWV0aW5nAARuYW1lAANvdXQAB3ByaW50bG4ABXZhbHVl" + +"AIwBfn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwiaGFzLWNoZWNrc3VtcyI6ZmFsc2Us" + +"Im1pbi1hcGkiOjEsInNoYS0xIjoiMTI5ZWU5ZjY3NTZjMzlkZjU3ZmYwNzg1ZDI1NmIyMzc3MjY0" + +"MmI3YyIsInZlcnNpb24iOiIyLjAuMTAtZGV2In0AAgIBFRgBAgMCDwQJEhcMAAEBAQABAIGABNgC" + +"AQT4AgAAAAACAAAAdQMAAHsDAACYAwAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAEAAAAX" + +"AAAAcAAAAAIAAAAJAAAAzAAAAAMAAAACAAAA8AAAAAQAAAACAAAACAEAAAUAAAAEAAAAGAEAAAYA" + +"AAABAAAAOAEAAAEgAAACAAAAWAEAAAMgAAACAAAAmAEAAAEQAAABAAAApAEAAAIgAAAXAAAAqgEA" + +"AAQgAAACAAAAdQMAAAAgAAABAAAAhAMAAAMQAAACAAAAlAMAAAYgAAABAAAApAMAAAAQAAABAAAA" + +"tAMAAA=="); + + public static void run() throws Exception { + Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); + doTest(); + } + + public static final class GcThread extends Thread { + public volatile boolean finished = false; + public void run() { + while (!finished) { + Runtime.getRuntime().gc(); + System.runFinalization(); + } + } + } + + public static void doTest() throws Exception { + GcThread gc_thr = new GcThread(); + gc_thr.start(); + mktransform(); + start_latch.await(); + System.out.println("start_counter: " + start_counter); + Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); + redefine_latch.countDown(); + finish_latch.await(); + System.out.println("Finish_counter: " + finish_counter); + gc_thr.finished = true; + gc_thr.join(); + } + public static void mktransform() throws Exception { + Transform tr = new Transform(); + } +} diff --git a/test/2006-virtual-structural-finalizing/src/Main.java b/test/2006-virtual-structural-finalizing/src/Main.java new file mode 100644 index 0000000000..89b8557970 --- /dev/null +++ b/test/2006-virtual-structural-finalizing/src/Main.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 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. + */ + +public class Main { + public static void main(String[] args) throws Exception { + System.out.println("FAIL: Test is only for art!"); + } +} diff --git a/test/2007-virtual-structural-finalizable/expected.txt b/test/2007-virtual-structural-finalizable/expected.txt new file mode 100644 index 0000000000..781fc9ae5d --- /dev/null +++ b/test/2007-virtual-structural-finalizable/expected.txt @@ -0,0 +1,2 @@ +Finalizing +counter: 1 diff --git a/test/2007-virtual-structural-finalizable/info.txt b/test/2007-virtual-structural-finalizable/info.txt new file mode 100644 index 0000000000..3e5291df87 --- /dev/null +++ b/test/2007-virtual-structural-finalizable/info.txt @@ -0,0 +1,4 @@ +Tests structural redefinition with multiple threads. + +Tests that using the structural redefinition while concurrently loading and using a subtype of +the class being redefined doesn't cause any unexpected problems. diff --git a/test/2007-virtual-structural-finalizable/run b/test/2007-virtual-structural-finalizable/run new file mode 100755 index 0000000000..03e41a58e7 --- /dev/null +++ b/test/2007-virtual-structural-finalizable/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 --runtime-option -Xopaque-jni-ids:true diff --git a/test/2007-virtual-structural-finalizable/src-art/Main.java b/test/2007-virtual-structural-finalizable/src-art/Main.java new file mode 100644 index 0000000000..ab8daeacad --- /dev/null +++ b/test/2007-virtual-structural-finalizable/src-art/Main.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 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. + */ + +public class Main { + public static void main(String[] args) throws Exception { + art.Test2007.run(); + } +} diff --git a/test/2007-virtual-structural-finalizable/src-art/art/Redefinition.java b/test/2007-virtual-structural-finalizable/src-art/art/Redefinition.java new file mode 120000 index 0000000000..81eaf31bbb --- /dev/null +++ b/test/2007-virtual-structural-finalizable/src-art/art/Redefinition.java @@ -0,0 +1 @@ +../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/2007-virtual-structural-finalizable/src-art/art/Test2007.java b/test/2007-virtual-structural-finalizable/src-art/art/Test2007.java new file mode 100644 index 0000000000..77284ebad5 --- /dev/null +++ b/test/2007-virtual-structural-finalizable/src-art/art/Test2007.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2019 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 dalvik.system.InMemoryDexClassLoader; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Base64; +import java.util.concurrent.CountDownLatch; +import java.util.function.Supplier; +import java.util.concurrent.atomic.*; +import java.lang.ref.*; + +public class Test2007 { + public static final CountDownLatch finish_latch = new CountDownLatch(1); + public static volatile int counter = 0; + public static Object theObject = null; + public static class Transform { + public Transform() { } + protected void finalize() throws Throwable { + System.out.println("Should never be called!"); + // Do nothing. + } + } + + /** + * base64 encoded class/dex file for + * public static class Transform { + * public String greeting; + * + * public Transform() { + * greeting = "Hello"; + * } + * protected void finalize() throws Throwable { + * System.out.println("Finalizing"); + * counter++; + * finish_latch.countDown(); + * } + * } + */ + private static final byte[] DEX_BYTES = + Base64.getDecoder() + .decode( +"ZGV4CjAzNQCC9DECxo2lTpw7FCCSqZArgZe8ab49ywRoBQAAcAAAAHhWNBIAAAAAAAAAAKQEAAAe" + +"AAAAcAAAAA0AAADoAAAAAgAAABwBAAAEAAAANAEAAAUAAABUAQAAAQAAAHwBAADMAwAAnAEAAAYC" + +"AAAOAgAAGgIAACECAAAkAgAAPgIAAE4CAAByAgAAkgIAAK4CAADFAgAA2QIAAO0CAAABAwAAGAMA" + +"AD8DAABOAwAAWQMAAFwDAABgAwAAbQMAAHgDAACBAwAAiwMAAJkDAACjAwAAqQMAAK4DAAC3AwAA" + +"vgMAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAABEAAAAR" + +"AAAADAAAAAAAAAASAAAADAAAAAACAAABAAgAGAAAAAIAAAAVAAAAAgALABcAAAAJAAYAGgAAAAEA" + +"AAAAAAAAAQAAABYAAAAGAAEAGwAAAAcAAAAAAAAACwAAABQAAAABAAAAAQAAAAcAAAAAAAAADwAA" + +"AIwEAABkBAAAAAAAAAIAAQABAAAA8gEAAAgAAABwEAMAAQAaAAIAWxAAAA4AAwABAAIAAAD4AQAA" + +"EwAAAGIAAwAaAQEAbiACABAAYAABANgAAAFnAAEAYgACAG4QBAAAAA4ADAAOPEsAEAAOeGlaAAAB" + +"AAAACAAGPGluaXQ+AApGaW5hbGl6aW5nAAVIZWxsbwABSQAYTGFydC9UZXN0MjAwNyRUcmFuc2Zv" + +"cm07AA5MYXJ0L1Rlc3QyMDA3OwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAe" + +"TGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ABpMZGFsdmlrL2Fubm90YXRpb24vVGhyb3dz" + +"OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcv" + +"U3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07ABVMamF2YS9sYW5nL1Rocm93YWJsZTsAJUxqYXZh" + +"L3V0aWwvY29uY3VycmVudC9Db3VudERvd25MYXRjaDsADVRlc3QyMDA3LmphdmEACVRyYW5zZm9y" + +"bQABVgACVkwAC2FjY2Vzc0ZsYWdzAAljb3VudERvd24AB2NvdW50ZXIACGZpbmFsaXplAAxmaW5p" + +"c2hfbGF0Y2gACGdyZWV0aW5nAARuYW1lAANvdXQAB3ByaW50bG4ABXZhbHVlAIwBfn5EOHsiY29t" + +"cGlsYXRpb24tbW9kZSI6ImRlYnVnIiwiaGFzLWNoZWNrc3VtcyI6ZmFsc2UsIm1pbi1hcGkiOjEs" + +"InNoYS0xIjoiMTI5ZWU5ZjY3NTZjMzlkZjU3ZmYwNzg1ZDI1NmIyMzc3MjY0MmI3YyIsInZlcnNp" + +"b24iOiIyLjAuMTAtZGV2In0AAgUBHBwBGAoCAwEcGAICBAITBAkZFxAAAQEBAAEAgYAEnAMBBLwD" + +"AAAAAAEAAABNBAAAAgAAAFUEAABbBAAAgAQAAAAAAAABAAAAAAAAAAEAAAB4BAAAEAAAAAAAAAAB" + +"AAAAAAAAAAEAAAAeAAAAcAAAAAIAAAANAAAA6AAAAAMAAAACAAAAHAEAAAQAAAAEAAAANAEAAAUA" + +"AAAFAAAAVAEAAAYAAAABAAAAfAEAAAEgAAACAAAAnAEAAAMgAAACAAAA8gEAAAEQAAABAAAAAAIA" + +"AAIgAAAeAAAABgIAAAQgAAADAAAATQQAAAAgAAABAAAAZAQAAAMQAAADAAAAdAQAAAYgAAABAAAA" + +"jAQAAAAQAAABAAAApAQAAA=="); + + + public static void run() throws Exception { + Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); + doTest(); + } + + public static final class GcThread extends Thread { + public volatile boolean finished = false; + public void run() { + while (!finished) { + Runtime.getRuntime().gc(); + System.runFinalization(); + } + } + } + + public static void doTest() throws Exception { + // Try GC forever + GcThread gc_thr = new GcThread(); + gc_thr.start(); + // Make a transform + mktransform(); + Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); + theObject = null; + finish_latch.await(); + System.out.println("counter: " + counter); + // Make sure we don't have any remaining things to finalize, eg obsolete objects or something. + Runtime.getRuntime().gc(); + System.runFinalization(); + gc_thr.finished = true; + gc_thr.join(); + } + + // Make sure there is never a transform in the frame of doTest. + public static void mktransform() throws Exception { + theObject = new Transform(); + } +} diff --git a/test/2007-virtual-structural-finalizable/src/Main.java b/test/2007-virtual-structural-finalizable/src/Main.java new file mode 100644 index 0000000000..89b8557970 --- /dev/null +++ b/test/2007-virtual-structural-finalizable/src/Main.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 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. + */ + +public class Main { + public static void main(String[] args) throws Exception { + System.out.println("FAIL: Test is only for art!"); + } +} |