1 /* 2 * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 5002251 6407335 6412391 27 * @summary Redefine a class that has an annotation and verify that the 28 * new annotation is returned. 29 * @comment converted from test/jdk/com/sun/jdi/RedefineAnnotation.sh 30 * 31 * @library /test/lib 32 * @compile -g RedefineAnnotation.java 33 * @run main/othervm RedefineAnnotation 34 */ 35 36 import jdk.test.lib.process.OutputAnalyzer; 37 import lib.jdb.JdbCommand; 38 import lib.jdb.JdbTest; 39 40 import java.lang.annotation.*; 41 import java.lang.reflect.*; 42 43 @Foo(Constants.class_annotation) // @1 commentout 44 // @1 uncomment @Foo(Constants.new_class_annotation) 45 class RedefineAnnotationTarg { 46 @Foo(Constants.field_annotation) // @1 commentout 47 // @1 uncomment @Foo(Constants.new_field_annotation) 48 public int dummy_field; 49 main(String[] args)50 public static void main(String[] args) { 51 MySubClass sub = new MySubClass(); 52 MySubSubClass subsub = new MySubSubClass(); 53 new RedefineAnnotationTarg().hi(false); 54 new RedefineAnnotationTarg().hi(true); // @1 breakpoint 55 sub.hi(true); 56 subsub.hi(true); 57 } 58 59 @Foo(Constants.method_annotation) // @1 commentout 60 // @1 uncomment @Foo(Constants.new_method_annotation) hi( @ooConstants.method_parameter_annotation) boolean isNewVersion)61 public void hi( 62 @Foo(Constants.method_parameter_annotation) // @1 commentout 63 // @1 uncomment @Foo(Constants.new_method_parameter_annotation) 64 boolean isNewVersion) { 65 66 if (isNewVersion) { 67 System.out.println("Checking for NEW versions of annotations in " 68 + getClass()); 69 } 70 71 // class annotations check: 72 Foo foo = getClass().getAnnotation(Foo.class); 73 if (foo == null) { 74 throw new Error("FAIL: cannot get class_annotation from " 75 + getClass()); 76 } 77 78 String class_annotation = foo.value(); 79 System.out.println("class annotation is: " + class_annotation); 80 if (isNewVersion) { 81 if (class_annotation.equals(Constants.new_class_annotation)) { 82 System.out.println("PASS: class_annotation was changed."); 83 } else { 84 System.out.println("FAIL: class_annotation was NOT changed."); 85 } 86 } 87 88 // field annotations check: 89 try { 90 Field my_field = getClass().getField("dummy_field"); 91 foo = my_field.getAnnotation(Foo.class); 92 if (foo == null) { 93 throw new Error("FAIL: cannot get field_annotation from " 94 + getClass() + ".dummy_field"); 95 } 96 String field_annotation = foo.value(); 97 System.out.println("field annotation is: " + field_annotation); 98 if (isNewVersion) { 99 if (field_annotation.equals(Constants.new_field_annotation)) { 100 System.out.println("PASS: field_annotation was changed."); 101 } else { 102 System.out.println( 103 "FAIL: field_annotation was NOT changed."); 104 } 105 } 106 } catch (NoSuchFieldException nsfe) { 107 throw new Error("FAIL: cannot find field 'dummy_field' in " 108 + getClass()); 109 } 110 111 // method annotations check: 112 try { 113 Class params[] = new Class[1]; 114 params[0] = Boolean.TYPE; 115 Method my_method = getClass().getMethod("hi", params); 116 foo = my_method.getAnnotation(Foo.class); 117 if (foo == null) { 118 throw new Error("FAIL: cannot get field_annotation from " 119 + getClass() + ".hi()"); 120 } 121 String method_annotation = foo.value(); 122 System.out.println("method annotation is: " + method_annotation); 123 if (isNewVersion) { 124 if (method_annotation.equals(Constants.new_method_annotation)) { 125 System.out.println("PASS: method_annotation was changed."); 126 } else { 127 System.out.println( 128 "FAIL: method_annotation was NOT changed."); 129 } 130 } 131 } catch (NoSuchMethodException nsme) { 132 throw new Error("FAIL: cannot find method 'hi' in " + getClass()); 133 } 134 135 // method parameter annotations check: 136 try { 137 Class params[] = new Class[1]; 138 params[0] = Boolean.TYPE; 139 Method my_method = getClass().getMethod("hi", params); 140 Annotation my_annotations[][] = my_method.getParameterAnnotations(); 141 if (my_annotations.length != 1) { 142 throw new Error("FAIL: unexpected my_annotations.length (" 143 + my_annotations.length); 144 } 145 Annotation my_annotation[] = my_annotations[0]; 146 if (my_annotation.length != 1) { 147 throw new Error("FAIL: unexpected my_annotation.length (" 148 + my_annotation.length); 149 } 150 foo = (Foo)my_annotation[0]; 151 String method_parameter_annotation = foo.value(); 152 System.out.println("method parameter annotation is: " 153 + method_parameter_annotation); 154 if (isNewVersion) { 155 if (method_parameter_annotation.equals( 156 Constants.new_method_parameter_annotation)) { 157 System.out.println( 158 "PASS: method_parameter_annotation was changed."); 159 } else { 160 System.out.println( 161 "FAIL: method_parameter_annotation was NOT changed."); 162 } 163 } 164 } catch (NoSuchMethodException nsme) { 165 throw new Error("FAIL: cannot find method 'hi' in " + getClass()); 166 } 167 } 168 } 169 170 // this subclass exists just to make the RedefineClasses() code do a 171 // subclass walk to update the counter 172 class MySubClass extends RedefineAnnotationTarg { 173 int my_int_field_makes_me_different; 174 } 175 176 // this subclass exists just to make the RedefineClasses() code do a 177 // sub-subclass walk to update the counter 178 class MySubSubClass extends MySubClass { 179 float my_float_field_makes_me_different; 180 } 181 182 class Constants { 183 static final String class_annotation = "Patrick's class comment"; 184 static final String new_class_annotation = "*NEW* Patrick's class comment"; 185 186 static final String field_annotation = "dummy_field comment"; 187 static final String new_field_annotation = "*NEW* dummy_field comment"; 188 189 static final String method_annotation = "method hi() comment"; 190 static final String new_method_annotation = "*NEW* method hi() comment"; 191 192 static final String method_parameter_annotation = 193 "param isNewVersion comment"; 194 static final String new_method_parameter_annotation = 195 "*NEW* param isNewVersion comment"; 196 } 197 198 199 /** 200 */ 201 @Retention(RetentionPolicy.RUNTIME) 202 @Inherited 203 @interface Foo { value()204 String value(); 205 } 206 207 public class RedefineAnnotation extends JdbTest { 208 main(String argv[])209 public static void main(String argv[]) { 210 new RedefineAnnotation().run(); 211 } 212 RedefineAnnotation()213 private RedefineAnnotation() { 214 super(DEBUGGEE_CLASS, SOURCE_FILE); 215 } 216 217 private static final String DEBUGGEE_CLASS = RedefineAnnotationTarg.class.getName(); 218 private static final String SOURCE_FILE = "RedefineAnnotation.java"; 219 220 @Override runCases()221 protected void runCases() { 222 setBreakpoints(1); 223 jdb.command(JdbCommand.run()); 224 225 redefineClass(1, "-g"); 226 jdb.contToExit(1); 227 228 new OutputAnalyzer(getDebuggeeOutput()) 229 .shouldNotContain("FAIL:"); 230 } 231 } 232