1 /* 2 * Copyright (c) 2016, 2017, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * Create class file using ASM, slightly modified the ASMifier output 28 */ 29 30 31 32 import java.io.File; 33 import java.io.FileOutputStream; 34 import java.io.IOException; 35 import jdk.internal.org.objectweb.asm.*; 36 37 38 public class ClassFileGenerator { 39 40 public static void main(String... args) throws Exception { 41 classFileWriter("AnnotationWithVoidReturn.class", AnnoationWithVoidReturnDump.dump()); 42 classFileWriter("AnnotationWithParameter.class", AnnoationWithParameterDump.dump()); 43 classFileWriter("AnnotationWithExtraInterface.class", AnnotationWithExtraInterfaceDump.dump()); 44 classFileWriter("AnnotationWithException.class", AnnotationWithExceptionDump.dump()); 45 classFileWriter("AnnotationWithHashCode.class", AnnotationWithHashCodeDump.dump()); 46 classFileWriter("AnnotationWithDefaultMember.class", AnnotationWithDefaultMemberDump.dump()); 47 classFileWriter("AnnotationWithoutAnnotationAccessModifier.class", 48 AnnotationWithoutAnnotationAccessModifierDump.dump()); 49 classFileWriter("HolderX.class", HolderXDump.dump()); 50 } 51 52 private static void classFileWriter(String name, byte[] contents) throws IOException { 53 try (FileOutputStream fos = new FileOutputStream(new File(System.getProperty("test.classes"), 54 name))) { 55 fos.write(contents); 56 } 57 } 58 59 /* Following code creates equivalent classfile, which is not allowed by javac: 60 61 @Retention(RetentionPolicy.RUNTIME) 62 public @interface AnnotationWithVoidReturn { 63 void m() default 1; 64 } 65 66 */ 67 68 private static class AnnoationWithVoidReturnDump implements Opcodes { 69 public static byte[] dump() throws Exception { 70 ClassWriter cw = new ClassWriter(0); 71 MethodVisitor mv; 72 AnnotationVisitor av0; 73 74 cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + ACC_INTERFACE, 75 "AnnotationWithVoidReturn", null, 76 "java/lang/Object", new String[]{"java/lang/annotation/Annotation"}); 77 78 { 79 av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true); 80 av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", 81 "RUNTIME"); 82 av0.visitEnd(); 83 } 84 { 85 mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()V", null, null); 86 mv.visitEnd(); 87 } 88 { 89 av0 = mv.visitAnnotationDefault(); 90 av0.visit(null, new Integer(1)); 91 av0.visitEnd(); 92 } 93 cw.visitEnd(); 94 95 return cw.toByteArray(); 96 97 } 98 } 99 100 /* Following code creates equivalent classfile, which is not allowed by javac: 101 102 @Retention(RetentionPolicy.RUNTIME) 103 public @interface AnnotationWithParameter { 104 int m(int x) default -1; 105 } 106 107 */ 108 109 private static class AnnoationWithParameterDump implements Opcodes { 110 public static byte[] dump() throws Exception { 111 112 ClassWriter cw = new ClassWriter(0); 113 MethodVisitor mv; 114 AnnotationVisitor av0; 115 116 cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + ACC_INTERFACE, 117 "AnnotationWithParameter", null, 118 "java/lang/Object", new String[]{"java/lang/annotation/Annotation"}); 119 120 { 121 av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true); 122 av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", 123 "RUNTIME"); 124 av0.visitEnd(); 125 } 126 { 127 mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, 128 "badValue", 129 "(I)I", // Bad method with a parameter 130 null, null); 131 mv.visitEnd(); 132 } 133 { 134 av0 = mv.visitAnnotationDefault(); 135 av0.visit(null, new Integer(-1)); 136 av0.visitEnd(); 137 } 138 cw.visitEnd(); 139 140 return cw.toByteArray(); 141 } 142 } 143 144 /* Following code creates equivalent classfile, which is not allowed by javac: 145 146 @Retention(RetentionPolicy.RUNTIME) 147 public @interface AnnotationWithExtraInterface extends java.io.Serializable { 148 int m() default 1; 149 } 150 151 */ 152 153 private static class AnnotationWithExtraInterfaceDump implements Opcodes { 154 public static byte[] dump() throws Exception { 155 ClassWriter cw = new ClassWriter(0); 156 MethodVisitor mv; 157 AnnotationVisitor av0; 158 159 cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + ACC_INTERFACE, 160 "AnnotationWithExtraInterface", null, 161 "java/lang/Object", new String[]{"java/lang/annotation/Annotation", 162 "java/io/Serializable"}); 163 164 { 165 av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true); 166 av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", 167 "RUNTIME"); 168 av0.visitEnd(); 169 } 170 { 171 mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, null); 172 mv.visitEnd(); 173 } 174 { 175 av0 = mv.visitAnnotationDefault(); 176 av0.visit(null, new Integer(1)); 177 av0.visitEnd(); 178 } 179 cw.visitEnd(); 180 181 return cw.toByteArray(); 182 } 183 } 184 185 /* Following code creates equivalent classfile, which is not allowed by javac: 186 187 @Retention(RetentionPolicy.RUNTIME) 188 public @interface AnnotationWithException { 189 int m() throws Exception default 1; 190 } 191 192 */ 193 194 private static class AnnotationWithExceptionDump implements Opcodes { 195 public static byte[] dump() throws Exception { 196 ClassWriter cw = new ClassWriter(0); 197 MethodVisitor mv; 198 AnnotationVisitor av0; 199 200 cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + ACC_INTERFACE, 201 "AnnotationWithException", null, 202 "java/lang/Object", new String[]{"java/lang/annotation/Annotation"}); 203 204 { 205 av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true); 206 av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", 207 "RUNTIME"); 208 av0.visitEnd(); 209 } 210 { 211 mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, 212 new String[] {"java/lang/Exception"}); 213 mv.visitEnd(); 214 } 215 { 216 av0 = mv.visitAnnotationDefault(); 217 av0.visit(null, new Integer(1)); 218 av0.visitEnd(); 219 } 220 cw.visitEnd(); 221 222 return cw.toByteArray(); 223 } 224 } 225 226 /* Following code creates equivalent classfile, which is not allowed by javac: 227 228 @Retention(RetentionPolicy.RUNTIME) 229 public @interface AnnotationWithHashCode { 230 int hashCode() default 1; 231 } 232 233 */ 234 235 private static class AnnotationWithHashCodeDump implements Opcodes { 236 public static byte[] dump() throws Exception { 237 ClassWriter cw = new ClassWriter(0); 238 MethodVisitor mv; 239 AnnotationVisitor av0; 240 241 cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + ACC_INTERFACE, 242 "AnnotationWithHashCode", null, 243 "java/lang/Object", new String[]{"java/lang/annotation/Annotation"}); 244 245 { 246 av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true); 247 av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", 248 "RUNTIME"); 249 av0.visitEnd(); 250 } 251 { 252 mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "hashCode", "()I", null, null); 253 mv.visitEnd(); 254 } 255 { 256 av0 = mv.visitAnnotationDefault(); 257 av0.visit(null, new Integer(1)); 258 av0.visitEnd(); 259 } 260 cw.visitEnd(); 261 262 return cw.toByteArray(); 263 } 264 } 265 266 /* Following code creates equivalent classfile, which is not allowed by javac: 267 268 @Retention(RetentionPolicy.RUNTIME) 269 public @interface AnnotationWithDefaultMember { 270 int m() default 1; 271 default int d() default 2 { return 2; } 272 } 273 274 */ 275 276 private static class AnnotationWithDefaultMemberDump implements Opcodes { 277 public static byte[] dump() throws Exception { 278 ClassWriter cw = new ClassWriter(0); 279 MethodVisitor mv, dv; 280 AnnotationVisitor av0; 281 282 cw.visit(52, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT + ACC_INTERFACE, 283 "AnnotationWithDefaultMember", null, 284 "java/lang/Object", new String[]{"java/lang/annotation/Annotation"}); 285 286 { 287 av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true); 288 av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", 289 "RUNTIME"); 290 av0.visitEnd(); 291 } 292 { 293 mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, null); 294 mv.visitEnd(); 295 } 296 { 297 av0 = mv.visitAnnotationDefault(); 298 av0.visit(null, new Integer(1)); 299 av0.visitEnd(); 300 } 301 { 302 dv = cw.visitMethod(ACC_PUBLIC, "d", "()I", null, null); 303 dv.visitMaxs(1, 1); 304 dv.visitCode(); 305 dv.visitInsn(Opcodes.ICONST_2); 306 dv.visitInsn(Opcodes.IRETURN); 307 dv.visitEnd(); 308 } 309 { 310 av0 = dv.visitAnnotationDefault(); 311 av0.visit(null, new Integer(2)); 312 av0.visitEnd(); 313 } 314 cw.visitEnd(); 315 316 return cw.toByteArray(); 317 } 318 } 319 320 /* Following code creates equivalent classfile, which is not allowed by javac: 321 322 @Retention(RetentionPolicy.RUNTIME) 323 public interface AnnotationWithoutAnnotationAccessModifier extends java.lang.annotation.Annotation { 324 int m() default 1; 325 } 326 327 */ 328 329 private static class AnnotationWithoutAnnotationAccessModifierDump implements Opcodes { 330 public static byte[] dump() throws Exception { 331 ClassWriter cw = new ClassWriter(0); 332 MethodVisitor mv; 333 AnnotationVisitor av0; 334 335 cw.visit(52, ACC_PUBLIC + /* ACC_ANNOTATION +*/ ACC_ABSTRACT + ACC_INTERFACE, 336 "AnnotationWithoutAnnotationAccessModifier", null, 337 "java/lang/Object", new String[]{"java/lang/annotation/Annotation"}); 338 339 { 340 av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true); 341 av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", 342 "RUNTIME"); 343 av0.visitEnd(); 344 } 345 { 346 mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, null); 347 mv.visitEnd(); 348 } 349 { 350 av0 = mv.visitAnnotationDefault(); 351 av0.visit(null, new Integer(1)); 352 av0.visitEnd(); 353 } 354 cw.visitEnd(); 355 356 return cw.toByteArray(); 357 } 358 } 359 360 /* Following code creates equivalent classfile, which is not allowed by javac 361 since AnnotationWithoutAnnotationAccessModifier is not marked with ACC_ANNOTATION: 362 363 @GoodAnnotation 364 @AnnotationWithoutAnnotationAccessModifier 365 public interface HolderX { 366 } 367 368 */ 369 370 private static class HolderXDump implements Opcodes { 371 public static byte[] dump() throws Exception { 372 ClassWriter cw = new ClassWriter(0); 373 374 cw.visit(52, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, 375 "HolderX", null, 376 "java/lang/Object", new String[0]); 377 378 { 379 AnnotationVisitor av0; 380 av0 = cw.visitAnnotation("LGoodAnnotation;", true); 381 av0.visitEnd(); 382 av0 = cw.visitAnnotation("LAnnotationWithoutAnnotationAccessModifier;", true); 383 av0.visitEnd(); 384 } 385 cw.visitEnd(); 386 387 return cw.toByteArray(); 388 } 389 } 390 }