Java tutorial
// ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. package org.objectweb.asm; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.util.regex.Pattern; /** * Defines additional JVM opcodes, access flags and constants which are not part of the ASM public * API. * * @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a> * @author Eric Bruneton */ final class Constants implements Opcodes { // The ClassFile attribute names, in the order they are defined in // https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300. static final String CONSTANT_VALUE = "ConstantValue"; static final String CODE = "Code"; static final String STACK_MAP_TABLE = "StackMapTable"; static final String EXCEPTIONS = "Exceptions"; static final String INNER_CLASSES = "InnerClasses"; static final String ENCLOSING_METHOD = "EnclosingMethod"; static final String SYNTHETIC = "Synthetic"; static final String SIGNATURE = "Signature"; static final String SOURCE_FILE = "SourceFile"; static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension"; static final String LINE_NUMBER_TABLE = "LineNumberTable"; static final String LOCAL_VARIABLE_TABLE = "LocalVariableTable"; static final String LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable"; static final String DEPRECATED = "Deprecated"; static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"; static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations"; static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations"; static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations"; static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations"; static final String ANNOTATION_DEFAULT = "AnnotationDefault"; static final String BOOTSTRAP_METHODS = "BootstrapMethods"; static final String METHOD_PARAMETERS = "MethodParameters"; static final String MODULE = "Module"; static final String MODULE_PACKAGES = "ModulePackages"; static final String MODULE_MAIN_CLASS = "ModuleMainClass"; static final String NEST_HOST = "NestHost"; static final String NEST_MEMBERS = "NestMembers"; static final String PERMITTED_SUBTYPES = "PermittedSubtypes"; static final String RECORD = "Record"; // ASM specific access flags. // WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard // access flags, and also to make sure that these flags are automatically filtered out when // written in class files (because access flags are stored using 16 bits only). static final int ACC_CONSTRUCTOR = 0x40000; // method access flag. // ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}. /** * A frame inserted between already existing frames. This internal stack map frame type (in * addition to the ones declared in {@link Opcodes}) can only be used if the frame content can be * computed from the previous existing frame and from the instructions between this existing frame * and the inserted one, without any knowledge of the type hierarchy. This kind of frame is only * used when an unconditional jump is inserted in a method while expanding an ASM specific * instruction. Keep in sync with Opcodes.java. */ static final int F_INSERT = 256; // The JVM opcode values which are not part of the ASM public API. // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html. static final int LDC_W = 19; static final int LDC2_W = 20; static final int ILOAD_0 = 26; static final int ILOAD_1 = 27; static final int ILOAD_2 = 28; static final int ILOAD_3 = 29; static final int LLOAD_0 = 30; static final int LLOAD_1 = 31; static final int LLOAD_2 = 32; static final int LLOAD_3 = 33; static final int FLOAD_0 = 34; static final int FLOAD_1 = 35; static final int FLOAD_2 = 36; static final int FLOAD_3 = 37; static final int DLOAD_0 = 38; static final int DLOAD_1 = 39; static final int DLOAD_2 = 40; static final int DLOAD_3 = 41; static final int ALOAD_0 = 42; static final int ALOAD_1 = 43; static final int ALOAD_2 = 44; static final int ALOAD_3 = 45; static final int ISTORE_0 = 59; static final int ISTORE_1 = 60; static final int ISTORE_2 = 61; static final int ISTORE_3 = 62; static final int LSTORE_0 = 63; static final int LSTORE_1 = 64; static final int LSTORE_2 = 65; static final int LSTORE_3 = 66; static final int FSTORE_0 = 67; static final int FSTORE_1 = 68; static final int FSTORE_2 = 69; static final int FSTORE_3 = 70; static final int DSTORE_0 = 71; static final int DSTORE_1 = 72; static final int DSTORE_2 = 73; static final int DSTORE_3 = 74; static final int ASTORE_0 = 75; static final int ASTORE_1 = 76; static final int ASTORE_2 = 77; static final int ASTORE_3 = 78; static final int WIDE = 196; static final int GOTO_W = 200; static final int JSR_W = 201; // Constants to convert between normal and wide jump instructions. // The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP. static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - GOTO; // Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa. // The delta between the ASM_IFEQ, ..., ASM_IF_ACMPNE, ASM_GOTO and ASM_JSR opcodes // and IFEQ, ..., IF_ACMPNE, GOTO and JSR. static final int ASM_OPCODE_DELTA = 49; // The delta between the ASM_IFNULL and ASM_IFNONNULL opcodes and IFNULL and IFNONNULL. static final int ASM_IFNULL_OPCODE_DELTA = 20; // ASM specific opcodes, used for long forward jump instructions. static final int ASM_IFEQ = IFEQ + ASM_OPCODE_DELTA; static final int ASM_IFNE = IFNE + ASM_OPCODE_DELTA; static final int ASM_IFLT = IFLT + ASM_OPCODE_DELTA; static final int ASM_IFGE = IFGE + ASM_OPCODE_DELTA; static final int ASM_IFGT = IFGT + ASM_OPCODE_DELTA; static final int ASM_IFLE = IFLE + ASM_OPCODE_DELTA; static final int ASM_IF_ICMPEQ = IF_ICMPEQ + ASM_OPCODE_DELTA; static final int ASM_IF_ICMPNE = IF_ICMPNE + ASM_OPCODE_DELTA; static final int ASM_IF_ICMPLT = IF_ICMPLT + ASM_OPCODE_DELTA; static final int ASM_IF_ICMPGE = IF_ICMPGE + ASM_OPCODE_DELTA; static final int ASM_IF_ICMPGT = IF_ICMPGT + ASM_OPCODE_DELTA; static final int ASM_IF_ICMPLE = IF_ICMPLE + ASM_OPCODE_DELTA; static final int ASM_IF_ACMPEQ = IF_ACMPEQ + ASM_OPCODE_DELTA; static final int ASM_IF_ACMPNE = IF_ACMPNE + ASM_OPCODE_DELTA; static final int ASM_GOTO = GOTO + ASM_OPCODE_DELTA; static final int ASM_JSR = JSR + ASM_OPCODE_DELTA; static final int ASM_IFNULL = IFNULL + ASM_IFNULL_OPCODE_DELTA; static final int ASM_IFNONNULL = IFNONNULL + ASM_IFNULL_OPCODE_DELTA; static final int ASM_GOTO_W = 220; private Constants() { } static void checkAsm8Experimental(final Object caller) { Class<?> callerClass = caller.getClass(); String internalName = callerClass.getName().replace('.', '/'); if (!isWhitelisted(internalName)) { checkIsPreview(callerClass.getClassLoader().getResourceAsStream(internalName + ".class")); } } static boolean isWhitelisted(final String internalName) { if (!internalName.startsWith("org/objectweb/asm/")) { return false; } String member = "(Annotation|Class|Field|Method|Module|RecordComponent|Signature)"; return internalName.contains("Test$") || Pattern.matches("org/objectweb/asm/util/Trace" + member + "Visitor(\\$.*)?", internalName) || Pattern.matches("org/objectweb/asm/util/Check" + member + "Adapter(\\$.*)?", internalName); } static void checkIsPreview(final InputStream classInputStream) { if (classInputStream == null) { throw new IllegalStateException("Bytecode not available, can't check class version"); } int minorVersion; try (DataInputStream callerClassStream = new DataInputStream(classInputStream);) { callerClassStream.readInt(); minorVersion = callerClassStream.readUnsignedShort(); } catch (IOException ioe) { throw new IllegalStateException("I/O error, can't check class version", ioe); } if (minorVersion != 0xFFFF) { throw new IllegalStateException( "ASM8_EXPERIMENTAL can only be used by classes compiled with --enable-preview"); } } }