1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.bcel.generic; 18 19 import static org.junit.jupiter.api.Assertions.fail; 20 import static org.junit.jupiter.api.Assumptions.assumeFalse; 21 22 import org.apache.bcel.classfile.Code; 23 import org.apache.bcel.classfile.JavaClass; 24 import org.apache.bcel.classfile.Method; 25 import org.apache.bcel.util.SyntheticRepository; 26 import org.apache.commons.lang3.JavaVersion; 27 import org.apache.commons.lang3.SystemUtils; 28 import org.junit.jupiter.params.ParameterizedTest; 29 import org.junit.jupiter.params.provider.ValueSource; 30 31 final class EmptyVisitorTestCase { 32 33 /* 34 * https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-6.html#jvms-6.2 35 */ 36 private static final String RESERVED_OPCODE = "Reserved opcode"; 37 38 @ParameterizedTest 39 @ValueSource(strings = { 40 // @formatter:off 41 "java.math.BigInteger", // contains instructions [AALOAD, AASTORE, ACONST_NULL, ALOAD, ANEWARRAY, ARETURN, ARRAYLENGTH, 42 // ASTORE, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CHECKCAST, D2I, DADD, DALOAD, DASTORE, DCONST 43 // DDIV, DMUL, DRETURN, DSUB, DUP, DUP2, DUP_X2, FCONST, FRETURN, GETFIELD, GETSTATIC, GOTO, I2B, 44 // I2D, I2L, IADD, IALOAD, IAND, IASTORE, ICONST, IDIV, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, 45 // IFNONNULL, IFNULL, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, 46 // IINC, ILOAD, IMUL, INEG, INSTANCEOF, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, IOR, IREM, 47 // IRETURN, ISHL, ISHR, ISTORE, ISUB, IUSHR, IXOR, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, 48 // LCONST, LDC, LDC2_W, LDC_W, LDIV, LLOAD, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, 49 // LSTORE, LSUB, LUSHR, NEW, NEWARRAY, POP, PUTFIELD, PUTSTATIC, RETURN, SIPUSH] 50 "java.math.BigDecimal", // contains instructions [CASTORE, D2L, DLOAD, FALOAD, FASTORE, FDIV, FMUL, I2S, IF_ACMPEQ, LXOR, 51 // MONITORENTER, MONITOREXIT, TABLESWITCH] 52 "java.awt.Color", // contains instructions [D2F, DCMPG, DCMPL, F2D, F2I, FADD, FCMPG, FCMPL, FLOAD, FSTORE, FSUB, I2F, 53 // INVOKEDYNAMIC] 54 "java.util.Map", // contains instruction INVOKEINTERFACE 55 "java.io.Bits", // contains instruction I2C 56 "java.io.BufferedInputStream", // contains instruction DUP_X1 57 "java.io.StreamTokenizer", // contains instruction DNEG, DSTORE 58 "java.lang.Float", // contains instruction F2L 59 "java.lang.invoke.LambdaForm", // contains instruction MULTIANEWARRAY, 60 "java.nio.Bits", // contains instruction POP2, 61 "java.nio.HeapShortBuffer", // contains instruction SALOAD, SASTORE 62 "Java8Example2", // contains instruction FREM 63 "java.awt.GradientPaintContext", // contains instruction DREM 64 "java.util.concurrent.atomic.DoubleAccumulator", // contains instruction DUP2_X1 65 "java.util.Hashtable", // contains instruction FNEG 66 "javax.swing.text.html.CSS", // contains instruction DUP2_X2 67 "org.apache.bcel.generic.LargeJump", // contains instruction GOTO_W 68 "org.apache.commons.lang.SerializationUtils" // contains instruction JSR 69 // @formatter:on 70 }) 71 public void test(final String className) throws ClassNotFoundException { 72 // "java.io.Bits" is not in Java 21. 73 assumeFalse(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_21) && className.equals("java.io.Bits")); 74 final JavaClass javaClass = SyntheticRepository.getInstance().loadClass(className); 75 for (final Method method : javaClass.getMethods()) { 76 final Code code = method.getCode(); 77 if (code != null) { 78 final InstructionList instructionList = new InstructionList(code.getCode()); 79 for (final InstructionHandle instructionHandle : instructionList) { 80 instructionHandle.accept(new EmptyVisitor() { 81 @Override 82 public void visitBREAKPOINT(final BREAKPOINT obj) { 83 fail(RESERVED_OPCODE); 84 } 85 86 @Override 87 public void visitIMPDEP1(final IMPDEP1 obj) { 88 fail(RESERVED_OPCODE); 89 } 90 91 @Override 92 public void visitIMPDEP2(final IMPDEP2 obj) { 93 fail(RESERVED_OPCODE); 94 } 95 }); 96 } 97 } 98 } 99 } 100 }