From f88f31dcbf80e9a4cd3ba9d34be8b88128af97c6 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Wed, 3 Apr 2024 00:23:36 +0000 Subject: [PATCH] 8328137: PreserveAllAnnotations can cause failure of class retransformation Reviewed-by: coleenp, sspitsyn --- .../prims/jvmtiClassFileReconstituter.cpp | 32 +++++++++++++------ .../prims/jvmtiClassFileReconstituter.hpp | 9 +++++- .../RetransformRecordAnnotation.java | 3 +- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp index 8efd803f6e0..08e25c793a6 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp @@ -119,10 +119,10 @@ void JvmtiClassFileReconstituter::write_field_infos() { write_signature_attribute(generic_signature_index); } if (anno != nullptr) { - write_annotations_attribute("RuntimeVisibleAnnotations", anno); + write_annotations_attribute("RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", anno); } if (type_anno != nullptr) { - write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno); + write_annotations_attribute("RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations", type_anno); } } } @@ -380,6 +380,20 @@ void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_n memcpy(writeable_address(length), annos->adr_at(0), length); } +void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_name, + const char* fallback_attr_name, + AnnotationArray* annos) { + TempNewSymbol sym = SymbolTable::probe(attr_name, (int)strlen(attr_name)); + if (sym != nullptr) { + if (symbol_to_cpool_index(sym) != 0) { + write_annotations_attribute(attr_name, annos); + return; + } + } + // use fallback name + write_annotations_attribute(fallback_attr_name, annos); +} + // BootstrapMethods_attribute { // u2 attribute_name_index; // u4 attribute_length; @@ -519,10 +533,10 @@ void JvmtiClassFileReconstituter::write_record_attribute() { write_signature_attribute(component->generic_signature_index()); } if (component->annotations() != nullptr) { - write_annotations_attribute("RuntimeVisibleAnnotations", component->annotations()); + write_annotations_attribute("RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", component->annotations()); } if (component->type_annotations() != nullptr) { - write_annotations_attribute("RuntimeVisibleTypeAnnotations", component->type_annotations()); + write_annotations_attribute("RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations", component->type_annotations()); } } } @@ -761,13 +775,13 @@ void JvmtiClassFileReconstituter::write_method_info(const methodHandle& method) write_signature_attribute(generic_signature_index); } if (anno != nullptr) { - write_annotations_attribute("RuntimeVisibleAnnotations", anno); + write_annotations_attribute("RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", anno); } if (param_anno != nullptr) { - write_annotations_attribute("RuntimeVisibleParameterAnnotations", param_anno); + write_annotations_attribute("RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", param_anno); } if (type_anno != nullptr) { - write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno); + write_annotations_attribute("RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations", type_anno); } } @@ -827,10 +841,10 @@ void JvmtiClassFileReconstituter::write_class_attributes() { write_source_debug_extension_attribute(); } if (anno != nullptr) { - write_annotations_attribute("RuntimeVisibleAnnotations", anno); + write_annotations_attribute("RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", anno); } if (type_anno != nullptr) { - write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno); + write_annotations_attribute("RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations", type_anno); } if (ik()->nest_host_index() != 0) { write_nest_host_attribute(); diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp index 25f3cbf7064..2f36a2877d2 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,6 +117,13 @@ class JvmtiClassFileReconstituter : public JvmtiConstantPoolReconstituter { void write_signature_attribute(u2 generic_signaure_index); void write_attribute_name_index(const char* name); void write_annotations_attribute(const char* attr_name, AnnotationArray* annos); + // With PreserveAllAnnotations option "runtime invisible" annotations + // (RuntimeInvisibleAnnotations/RuntimeInvisibleTypeAnnotations/RuntimeInvisibleParameterAnnotations) + // are considered "runtime visible" and ClassFileReconstituter writes them as + // RuntimeVisibleAnnotations/RuntimeVisibleTypeAnnotations/RuntimeVisibleParameterAnnotations. + // This helper method is for the corner case when "runtime visible" attribute name is not presents + // in the class constant pool and the annotations are written with fallback "runtime invisible" name. + void write_annotations_attribute(const char* attr_name, const char* fallback_attr_name, AnnotationArray* annos); void write_bootstrapmethod_attribute(); void write_nest_host_attribute(); void write_nest_members_attribute(); diff --git a/test/jdk/java/lang/instrument/RetransformRecordAnnotation.java b/test/jdk/java/lang/instrument/RetransformRecordAnnotation.java index 522a2609290..90d76d1f923 100644 --- a/test/jdk/java/lang/instrument/RetransformRecordAnnotation.java +++ b/test/jdk/java/lang/instrument/RetransformRecordAnnotation.java @@ -23,12 +23,13 @@ /* * @test - * @bug 8315575 + * @bug 8315575 8328137 * @summary test that records with invisible annotation can be retransformed * * @library /test/lib * @run shell MakeJAR.sh retransformAgent * @run main/othervm -javaagent:retransformAgent.jar -Xlog:redefine+class=trace RetransformRecordAnnotation + * @run main/othervm -javaagent:retransformAgent.jar -XX:+PreserveAllAnnotations -Xlog:redefine+class=trace RetransformRecordAnnotation */ import java.io.File;