diff options
author | 2019-11-06 10:28:21 -0800 | |
---|---|---|
committer | 2019-11-11 16:58:12 +0000 | |
commit | 2462789806df0281c52fa9bb60fa37fe3ff606b6 (patch) | |
tree | a26da1d669e88b34b10b0f6c76b06abd8b694473 | |
parent | 28b6efed2c2e38d3df787f8f68e2b8d55efabd06 (diff) |
Ensure structural redefinition can shadow functions/fields
Previously when we structurally redefined a class and a new field or
function shadowed a super type field or function the shadowed version
might still get called. This was due to the old version remaining in
the dex-caches of other classes. To fix this we just remove from all
dex-caches any entries that might be (invisibly) shadowed by a new
function/field. This is any non-virtual methods or non-private field
of a supertype of the redefined class with the same name & signature
as a method/field in the redefined class.
Test: ./test.py --host
Bug: 134162467
Change-Id: Iae8e7a3e7f8ecedbd2f314816b140156fce3e5fd
-rw-r--r-- | openjdkjvmti/ti_redefine.cc | 81 | ||||
-rw-r--r-- | runtime/art_field.h | 4 | ||||
-rw-r--r-- | runtime/mirror/dex_cache.cc | 12 | ||||
-rw-r--r-- | runtime/reflective_value_visitor.h | 4 | ||||
-rw-r--r-- | test/1997-structural-shadow-method/expected.txt | 6 | ||||
-rw-r--r-- | test/1997-structural-shadow-method/info.txt | 1 | ||||
-rwxr-xr-x | test/1997-structural-shadow-method/run | 17 | ||||
-rw-r--r-- | test/1997-structural-shadow-method/src/Main.java | 21 | ||||
l--------- | test/1997-structural-shadow-method/src/art/Redefinition.java | 1 | ||||
-rw-r--r-- | test/1997-structural-shadow-method/src/art/Test1997.java | 84 | ||||
-rw-r--r-- | test/1998-structural-shadow-field/expected.txt | 4 | ||||
-rw-r--r-- | test/1998-structural-shadow-field/info.txt | 1 | ||||
-rwxr-xr-x | test/1998-structural-shadow-field/run | 17 | ||||
-rw-r--r-- | test/1998-structural-shadow-field/src/Main.java | 21 | ||||
l--------- | test/1998-structural-shadow-field/src/art/Redefinition.java | 1 | ||||
-rw-r--r-- | test/1998-structural-shadow-field/src/art/Test1998.java | 65 | ||||
-rw-r--r-- | test/knownfailures.json | 4 |
17 files changed, 332 insertions, 12 deletions
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 46b7d11e6d..50dc09c3c2 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -112,6 +112,7 @@ #include "non_debuggable_classes.h" #include "obj_ptr.h" #include "object_lock.h" +#include "reflective_value_visitor.h" #include "runtime.h" #include "runtime_globals.h" #include "stack.h" @@ -1640,6 +1641,11 @@ bool Redefiner::ClassRedefinition::FinishRemainingAllocations( } cur_data->SetNewClassObject(nc.Get()); + // We really want to be able to resolve to the new class-object using this dex-cache for + // verification work. Since we haven't put it in the class-table yet we wll just manually add it + // to the dex-cache. + // TODO: We should maybe do this in a better spot. + cur_data->GetNewDexCache()->SetResolvedType(nc->GetDexTypeIndex(), nc.Get()); } return true; } @@ -2087,27 +2093,84 @@ void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDat replacement->SetLockWord(orig->GetLockWord(false), false); orig->SetLockWord(art::LockWord::Default(), false); // Update live pointers in ART code. + auto could_change_resolution_of = [&](auto* field_or_method, + const auto& info) REQUIRES(art::Locks::mutator_lock_) { + constexpr bool is_method = std::is_same_v<art::ArtMethod*, decltype(field_or_method)>; + static_assert(is_method || std::is_same_v<art::ArtField*, decltype(field_or_method)>, + "Input is not field or method!"); + // Only dex-cache is used for resolution + if (LIKELY(info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedField && + info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedMethod)) { + return false; + } + if constexpr (is_method) { + // Only direct methods are used without further indirection through a vtable/IFTable. + // Constructors cannot be shadowed. + if (LIKELY(!field_or_method->IsDirect() || field_or_method->IsConstructor())) { + return false; + } + } else { + // Only non-private fields can be shadowed in a manner that's visible. + if (LIKELY(field_or_method->IsPrivate())) { + return false; + } + } + // We can only shadow things from our superclasses + if (LIKELY(!field_or_method->GetDeclaringClass()->IsAssignableFrom(orig))) { + return false; + } + if constexpr (is_method) { + auto direct_methods = replacement->GetDirectMethods(art::kRuntimePointerSize); + return std::find_if(direct_methods.begin(), + direct_methods.end(), + [&](art::ArtMethod& m) REQUIRES(art::Locks::mutator_lock_) { + return UNLIKELY(m.HasSameNameAndSignature(field_or_method)); + }) != direct_methods.end(); + } else { + auto pred = [&](art::ArtField& f) REQUIRES(art::Locks::mutator_lock_) { + return std::string_view(f.GetName()) == std::string_view(field_or_method->GetName()) && + std::string_view(f.GetTypeDescriptor()) == + std::string_view(field_or_method->GetTypeDescriptor()); + }; + if (field_or_method->IsStatic()) { + auto sfields = replacement->GetSFields(); + return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end(); + } else { + auto ifields = replacement->GetIFields(); + return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end(); + } + } + }; // TODO Performing 2 stack-walks back to back isn't the greatest. We might want to try to combine // it with the one ReplaceReferences does. Doing so would be rather complicated though. driver_->runtime_->VisitReflectiveTargets( [&](art::ArtField* f, const auto& info) REQUIRES(art::Locks::mutator_lock_) { DCHECK(f != nullptr) << info; auto it = field_map.find(f); - if (it == field_map.end()) { - return f; + if (it != field_map.end()) { + VLOG(plugin) << "Updating " << info << " object for (field) " + << it->second->PrettyField(); + return it->second; + } else if (UNLIKELY(could_change_resolution_of(f, info))) { + // Resolution might change. Just clear the resolved value. + VLOG(plugin) << "Clearing resolution " << info << " for (field) " << f->PrettyField(); + return static_cast<art::ArtField*>(nullptr); } - VLOG(plugin) << "Updating " << info << " object for (field) " << it->second->PrettyField(); - return it->second; + return f; }, [&](art::ArtMethod* m, const auto& info) REQUIRES(art::Locks::mutator_lock_) { DCHECK(m != nullptr) << info; auto it = method_map.find(m); - if (it == method_map.end()) { - return m; + if (it != method_map.end()) { + VLOG(plugin) << "Updating " << info << " object for (method) " + << it->second->PrettyMethod(); + return it->second; + } else if (UNLIKELY(could_change_resolution_of(m, info))) { + // Resolution might change. Just clear the resolved value. + VLOG(plugin) << "Clearing resolution " << info << " for (method) " << m->PrettyMethod(); + return static_cast<art::ArtMethod*>(nullptr); } - VLOG(plugin) << "Updating " << info << " object for (method) " - << it->second->PrettyMethod(); - return it->second; + return m; }); // Force every frame of every thread to deoptimize (any frame might have eg offsets compiled in). diff --git a/runtime/art_field.h b/runtime/art_field.h index e44517e10b..bc2c399b74 100644 --- a/runtime/art_field.h +++ b/runtime/art_field.h @@ -75,6 +75,10 @@ class ArtField final { return (GetAccessFlags() & kAccFinal) != 0; } + bool IsPrivate() REQUIRES_SHARED(Locks::mutator_lock_) { + return (GetAccessFlags() & kAccPrivate) != 0; + } + uint32_t GetDexFieldIndex() { return field_dex_idx_; } diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index b503f0ac82..96fc403690 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -182,7 +182,11 @@ void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) { ArtField* new_val = visitor->VisitField( pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedField, pair.index, this)); if (UNLIKELY(new_val != pair.object)) { - pair.object = new_val; + if (new_val == nullptr) { + pair = FieldDexCachePair(nullptr, FieldDexCachePair::InvalidIndexForSlot(i)); + } else { + pair.object = new_val; + } SetNativePairPtrSize(GetResolvedFields(), i, pair, kRuntimePointerSize); } } @@ -194,7 +198,11 @@ void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) { ArtMethod* new_val = visitor->VisitMethod( pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedMethod, pair.index, this)); if (UNLIKELY(new_val != pair.object)) { - pair.object = new_val; + if (new_val == nullptr) { + pair = MethodDexCachePair(nullptr, MethodDexCachePair::InvalidIndexForSlot(i)); + } else { + pair.object = new_val; + } SetNativePairPtrSize(GetResolvedMethods(), i, pair, kRuntimePointerSize); } } diff --git a/runtime/reflective_value_visitor.h b/runtime/reflective_value_visitor.h index 0b09a0bf8a..3a72760345 100644 --- a/runtime/reflective_value_visitor.h +++ b/runtime/reflective_value_visitor.h @@ -109,6 +109,10 @@ class ReflectionSourceInfo : public ValueObject { os << "Type=" << type_; } + ReflectionSourceType GetType() const { + return type_; + } + private: const ReflectionSourceType type_; diff --git a/test/1997-structural-shadow-method/expected.txt b/test/1997-structural-shadow-method/expected.txt new file mode 100644 index 0000000000..3a8b8de39b --- /dev/null +++ b/test/1997-structural-shadow-method/expected.txt @@ -0,0 +1,6 @@ +Hello! +Hello! +Hello! +Hello World! +Hello World! +Hello World! diff --git a/test/1997-structural-shadow-method/info.txt b/test/1997-structural-shadow-method/info.txt new file mode 100644 index 0000000000..71e3bfcd2e --- /dev/null +++ b/test/1997-structural-shadow-method/info.txt @@ -0,0 +1 @@ +Test structural redefinition when the method being added was resolvable previously. diff --git a/test/1997-structural-shadow-method/run b/test/1997-structural-shadow-method/run new file mode 100755 index 0000000000..03e41a58e7 --- /dev/null +++ b/test/1997-structural-shadow-method/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/1997-structural-shadow-method/src/Main.java b/test/1997-structural-shadow-method/src/Main.java new file mode 100644 index 0000000000..3c9bc85fb3 --- /dev/null +++ b/test/1997-structural-shadow-method/src/Main.java @@ -0,0 +1,21 @@ +/* + * 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. + */ + +public class Main { + public static void main(String[] args) throws Exception { + art.Test1997.run(); + } +} diff --git a/test/1997-structural-shadow-method/src/art/Redefinition.java b/test/1997-structural-shadow-method/src/art/Redefinition.java new file mode 120000 index 0000000000..81eaf31bbb --- /dev/null +++ b/test/1997-structural-shadow-method/src/art/Redefinition.java @@ -0,0 +1 @@ +../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/1997-structural-shadow-method/src/art/Test1997.java b/test/1997-structural-shadow-method/src/art/Test1997.java new file mode 100644 index 0000000000..7309a31bd3 --- /dev/null +++ b/test/1997-structural-shadow-method/src/art/Test1997.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +package art; + +import java.util.Base64; + +public class Test1997 { + + public static class SuperTransform { + // We will be shadowing this function. + public static void sayHi() { + System.out.println("Hello!"); + } + } + + // The class we will be transforming. + public static class Transform extends SuperTransform { + public static void sayHiTwice() { + Transform.sayHi(); + Transform.sayHi(); + } + } + + // public static class Transform extends SuperTransform { + // public static void sayHiTwice() { + // Transform.sayHi(); + // Transform.sayHi(); + // } + // public static void sayHi() { + // System.out.println("Hello World!"); + // } + // } + private static final byte[] DEX_BYTES = + Base64.getDecoder() + .decode( + "ZGV4CjAzNQA9wdy7Lgbrv+sD+wixborREr0maZCK5yqABAAAcAAAAHhWNBIAAAAAAAAAALwDAAAW" + + "AAAAcAAAAAkAAADIAAAAAgAAAOwAAAABAAAABAEAAAUAAAAMAQAAAQAAADQBAAAsAwAAVAEAAMIB" + + "AADKAQAA2AEAAPcBAAARAgAAIQIAAEUCAABlAgAAfAIAAJACAACkAgAAswIAAL4CAADBAgAAxQIA" + + "ANICAADYAgAA3QIAAOYCAADtAgAA+QIAAAADAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAA" + + "CQAAAAwAAAAMAAAACAAAAAAAAAANAAAACAAAALwBAAAHAAUAEAAAAAAAAAAAAAAAAQAAAAAAAAAB" + + "AAAAEgAAAAEAAAATAAAABQABABEAAAABAAAAAQAAAAAAAAAAAAAACgAAAKwDAACHAwAAAAAAAAEA" + + "AQABAAAAqgEAAAQAAABwEAAAAAAOAAIAAAACAAAArgEAAAgAAABiAAAAGgEBAG4gBAAQAA4AAAAA" + + "AAAAAACzAQAABwAAAHEAAgAAAHEAAgAAAA4ADwAOABUADngAEQAOPDwAAAAAAQAAAAYABjxpbml0" + + "PgAMSGVsbG8gV29ybGQhAB1MYXJ0L1Rlc3QxOTk3JFN1cGVyVHJhbnNmb3JtOwAYTGFydC9UZXN0" + + "MTk5NyRUcmFuc2Zvcm07AA5MYXJ0L1Rlc3QxOTk3OwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xv" + + "c2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ABVMamF2YS9pby9Qcmlu" + + "dFN0cmVhbTsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AA1UZXN0MTk5" + + "Ny5qYXZhAAlUcmFuc2Zvcm0AAVYAAlZMAAthY2Nlc3NGbGFncwAEbmFtZQADb3V0AAdwcmludGxu" + + "AAVzYXlIaQAKc2F5SGlUd2ljZQAFdmFsdWUAdn5+RDh7ImNvbXBpbGF0aW9uLW1vZGUiOiJkZWJ1" + + "ZyIsIm1pbi1hcGkiOjEsInNoYS0xIjoiNjBkYTRkNjdiMzgxYzQyNDY3NzU3YzQ5ZmI2ZTU1NzU2" + + "ZDg4YTJmMyIsInZlcnNpb24iOiIxLjcuMTItZGV2In0AAgMBFBgCAgQCDgQJDxcLAAADAAGBgATU" + + "AgEJ7AIBCYwDAAAAAAAAAAIAAAB4AwAAfgMAAKADAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAEAAAAA" + + "AAAAAQAAABYAAABwAAAAAgAAAAkAAADIAAAAAwAAAAIAAADsAAAABAAAAAEAAAAEAQAABQAAAAUA" + + "AAAMAQAABgAAAAEAAAA0AQAAASAAAAMAAABUAQAAAyAAAAMAAACqAQAAARAAAAEAAAC8AQAAAiAA" + + "ABYAAADCAQAABCAAAAIAAAB4AwAAACAAAAEAAACHAwAAAxAAAAIAAACcAwAABiAAAAEAAACsAwAA" + + "ABAAAAEAAAC8AwAA"); + + public static void run() throws Exception { + Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); + doTest(); + } + + public static void doTest() throws Exception { + Transform.sayHiTwice(); + Transform.sayHi(); + Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); + Transform.sayHiTwice(); + Transform.sayHi(); + } +} diff --git a/test/1998-structural-shadow-field/expected.txt b/test/1998-structural-shadow-field/expected.txt new file mode 100644 index 0000000000..9ae530e728 --- /dev/null +++ b/test/1998-structural-shadow-field/expected.txt @@ -0,0 +1,4 @@ +Hello +Hello +null +Hello diff --git a/test/1998-structural-shadow-field/info.txt b/test/1998-structural-shadow-field/info.txt new file mode 100644 index 0000000000..71e3bfcd2e --- /dev/null +++ b/test/1998-structural-shadow-field/info.txt @@ -0,0 +1 @@ +Test structural redefinition when the method being added was resolvable previously. diff --git a/test/1998-structural-shadow-field/run b/test/1998-structural-shadow-field/run new file mode 100755 index 0000000000..03e41a58e7 --- /dev/null +++ b/test/1998-structural-shadow-field/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/1998-structural-shadow-field/src/Main.java b/test/1998-structural-shadow-field/src/Main.java new file mode 100644 index 0000000000..f6aeca5b85 --- /dev/null +++ b/test/1998-structural-shadow-field/src/Main.java @@ -0,0 +1,21 @@ +/* + * 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. + */ + +public class Main { + public static void main(String[] args) throws Exception { + art.Test1998.run(); + } +} diff --git a/test/1998-structural-shadow-field/src/art/Redefinition.java b/test/1998-structural-shadow-field/src/art/Redefinition.java new file mode 120000 index 0000000000..81eaf31bbb --- /dev/null +++ b/test/1998-structural-shadow-field/src/art/Redefinition.java @@ -0,0 +1 @@ +../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/1998-structural-shadow-field/src/art/Test1998.java b/test/1998-structural-shadow-field/src/art/Test1998.java new file mode 100644 index 0000000000..3fda936f84 --- /dev/null +++ b/test/1998-structural-shadow-field/src/art/Test1998.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package art; + +import java.util.Base64; + +public class Test1998 { + + public static class SuperTransform { + public static String greeting = "Hello"; + } + + // The class we will be transforming. + public static class Transform extends SuperTransform { } + + // public static class Transform extends SuperTransform { + // public static String greeting; + // } + private static final byte[] DEX_BYTES = + Base64.getDecoder() + .decode( +"ZGV4CjAzNQCYmnoWz4BqygrZQM4zf/mJ/25+dM86MHKAAwAAcAAAAHhWNBIAAAAAAAAAAMgCAAAP" + +"AAAAcAAAAAcAAACsAAAAAQAAAMgAAAABAAAA1AAAAAIAAADcAAAAAQAAAOwAAAB0AgAADAEAACgB" + +"AAAwAQAATwEAAGkBAAB5AQAAnQEAAL0BAADRAQAA4AEAAOsBAADuAQAA+wEAAAUCAAALAgAAEgIA" + +"AAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAkAAAAJAAAABgAAAAAAAAABAAUACwAAAAAAAAAAAAAA" + +"AQAAAAAAAAABAAAAAQAAAAAAAAAAAAAABwAAALgCAACZAgAAAAAAAAEAAQABAAAAJAEAAAQAAABw" + +"EAAAAAAOAAUADgAGPGluaXQ+AB1MYXJ0L1Rlc3QxOTk4JFN1cGVyVHJhbnNmb3JtOwAYTGFydC9U" + +"ZXN0MTk5OCRUcmFuc2Zvcm07AA5MYXJ0L1Rlc3QxOTk4OwAiTGRhbHZpay9hbm5vdGF0aW9uL0Vu" + +"Y2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ABJMamF2YS9sYW5n" + +"L1N0cmluZzsADVRlc3QxOTk4LmphdmEACVRyYW5zZm9ybQABVgALYWNjZXNzRmxhZ3MACGdyZWV0" + +"aW5nAARuYW1lAAV2YWx1ZQB2fn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwibWluLWFw" + +"aSI6MSwic2hhLTEiOiI2MGRhNGQ2N2IzODFjNDI0Njc3NTdjNDlmYjZlNTU3NTZkODhhMmYzIiwi" + +"dmVyc2lvbiI6IjEuNy4xMi1kZXYifQACAwENGAICBAIKBAkMFwgBAAEAAAkBgYAEjAIAAAAAAAAA" + +"AgAAAIoCAACQAgAArAIAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAAC" + +"AAAABwAAAKwAAAADAAAAAQAAAMgAAAAEAAAAAQAAANQAAAAFAAAAAgAAANwAAAAGAAAAAQAAAOwA" + +"AAABIAAAAQAAAAwBAAADIAAAAQAAACQBAAACIAAADwAAACgBAAAEIAAAAgAAAIoCAAAAIAAAAQAA" + +"AJkCAAADEAAAAgAAAKgCAAAGIAAAAQAAALgCAAAAEAAAAQAAAMgCAAA="); + + public static void run() throws Exception { + Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); + doTest(); + } + + public static void doTest() throws Exception { + System.out.println(Transform.greeting); + System.out.println(SuperTransform.greeting); + Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); + System.out.println(Transform.greeting); + System.out.println(SuperTransform.greeting); + } +} diff --git a/test/knownfailures.json b/test/knownfailures.json index 0134a547e7..cd66472aa8 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -1145,7 +1145,9 @@ "1990-structural-bad-verify", "1991-hello-structural-retransform", "1992-retransform-no-such-field", - "1993-fallback-non-structural" + "1993-fallback-non-structural", + "1997-structural-shadow-method", + "1998-structural-shadow-field" ], "variant": "jvm", "description": ["Doesn't run on RI."] |