• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // ASM: a very small and fast Java bytecode manipulation framework
2 // Copyright (c) 2000-2011 INRIA, France Telecom
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 // 1. Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the distribution.
13 // 3. Neither the name of the copyright holders nor the names of its
14 //    contributors may be used to endorse or promote products derived from
15 //    this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 // THE POSSIBILITY OF SUCH DAMAGE.
28 package org.objectweb.asm;
29 
30 import java.io.DataInputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.util.regex.Pattern;
34 
35 /**
36  * Defines additional JVM opcodes, access flags and constants which are not part of the ASM public
37  * API.
38  *
39  * @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
40  * @author Eric Bruneton
41  */
42 final class Constants {
43 
44   // The ClassFile attribute names, in the order they are defined in
45   // https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300.
46 
47   static final String CONSTANT_VALUE = "ConstantValue";
48   static final String CODE = "Code";
49   static final String STACK_MAP_TABLE = "StackMapTable";
50   static final String EXCEPTIONS = "Exceptions";
51   static final String INNER_CLASSES = "InnerClasses";
52   static final String ENCLOSING_METHOD = "EnclosingMethod";
53   static final String SYNTHETIC = "Synthetic";
54   static final String SIGNATURE = "Signature";
55   static final String SOURCE_FILE = "SourceFile";
56   static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
57   static final String LINE_NUMBER_TABLE = "LineNumberTable";
58   static final String LOCAL_VARIABLE_TABLE = "LocalVariableTable";
59   static final String LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";
60   static final String DEPRECATED = "Deprecated";
61   static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
62   static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
63   static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
64   static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS =
65       "RuntimeInvisibleParameterAnnotations";
66   static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
67   static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
68   static final String ANNOTATION_DEFAULT = "AnnotationDefault";
69   static final String BOOTSTRAP_METHODS = "BootstrapMethods";
70   static final String METHOD_PARAMETERS = "MethodParameters";
71   static final String MODULE = "Module";
72   static final String MODULE_PACKAGES = "ModulePackages";
73   static final String MODULE_MAIN_CLASS = "ModuleMainClass";
74   static final String NEST_HOST = "NestHost";
75   static final String NEST_MEMBERS = "NestMembers";
76   static final String PERMITTED_SUBCLASSES = "PermittedSubclasses";
77   static final String RECORD = "Record";
78 
79   // ASM specific access flags.
80   // WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
81   // access flags, and also to make sure that these flags are automatically filtered out when
82   // written in class files (because access flags are stored using 16 bits only).
83 
84   static final int ACC_CONSTRUCTOR = 0x40000; // method access flag.
85 
86   // ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
87 
88   /**
89    * A frame inserted between already existing frames. This internal stack map frame type (in
90    * addition to the ones declared in {@link Opcodes}) can only be used if the frame content can be
91    * computed from the previous existing frame and from the instructions between this existing frame
92    * and the inserted one, without any knowledge of the type hierarchy. This kind of frame is only
93    * used when an unconditional jump is inserted in a method while expanding an ASM specific
94    * instruction. Keep in sync with Opcodes.java.
95    */
96   static final int F_INSERT = 256;
97 
98   // The JVM opcode values which are not part of the ASM public API.
99   // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
100 
101   static final int LDC_W = 19;
102   static final int LDC2_W = 20;
103   static final int ILOAD_0 = 26;
104   static final int ILOAD_1 = 27;
105   static final int ILOAD_2 = 28;
106   static final int ILOAD_3 = 29;
107   static final int LLOAD_0 = 30;
108   static final int LLOAD_1 = 31;
109   static final int LLOAD_2 = 32;
110   static final int LLOAD_3 = 33;
111   static final int FLOAD_0 = 34;
112   static final int FLOAD_1 = 35;
113   static final int FLOAD_2 = 36;
114   static final int FLOAD_3 = 37;
115   static final int DLOAD_0 = 38;
116   static final int DLOAD_1 = 39;
117   static final int DLOAD_2 = 40;
118   static final int DLOAD_3 = 41;
119   static final int ALOAD_0 = 42;
120   static final int ALOAD_1 = 43;
121   static final int ALOAD_2 = 44;
122   static final int ALOAD_3 = 45;
123   static final int ISTORE_0 = 59;
124   static final int ISTORE_1 = 60;
125   static final int ISTORE_2 = 61;
126   static final int ISTORE_3 = 62;
127   static final int LSTORE_0 = 63;
128   static final int LSTORE_1 = 64;
129   static final int LSTORE_2 = 65;
130   static final int LSTORE_3 = 66;
131   static final int FSTORE_0 = 67;
132   static final int FSTORE_1 = 68;
133   static final int FSTORE_2 = 69;
134   static final int FSTORE_3 = 70;
135   static final int DSTORE_0 = 71;
136   static final int DSTORE_1 = 72;
137   static final int DSTORE_2 = 73;
138   static final int DSTORE_3 = 74;
139   static final int ASTORE_0 = 75;
140   static final int ASTORE_1 = 76;
141   static final int ASTORE_2 = 77;
142   static final int ASTORE_3 = 78;
143   static final int WIDE = 196;
144   static final int GOTO_W = 200;
145   static final int JSR_W = 201;
146 
147   // Constants to convert between normal and wide jump instructions.
148 
149   // The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP.
150   static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - Opcodes.GOTO;
151 
152   // Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa.
153 
154   // The delta between the ASM_IFEQ, ..., ASM_IF_ACMPNE, ASM_GOTO and ASM_JSR opcodes
155   // and IFEQ, ..., IF_ACMPNE, GOTO and JSR.
156   static final int ASM_OPCODE_DELTA = 49;
157 
158   // The delta between the ASM_IFNULL and ASM_IFNONNULL opcodes and IFNULL and IFNONNULL.
159   static final int ASM_IFNULL_OPCODE_DELTA = 20;
160 
161   // ASM specific opcodes, used for long forward jump instructions.
162 
163   static final int ASM_IFEQ = Opcodes.IFEQ + ASM_OPCODE_DELTA;
164   static final int ASM_IFNE = Opcodes.IFNE + ASM_OPCODE_DELTA;
165   static final int ASM_IFLT = Opcodes.IFLT + ASM_OPCODE_DELTA;
166   static final int ASM_IFGE = Opcodes.IFGE + ASM_OPCODE_DELTA;
167   static final int ASM_IFGT = Opcodes.IFGT + ASM_OPCODE_DELTA;
168   static final int ASM_IFLE = Opcodes.IFLE + ASM_OPCODE_DELTA;
169   static final int ASM_IF_ICMPEQ = Opcodes.IF_ICMPEQ + ASM_OPCODE_DELTA;
170   static final int ASM_IF_ICMPNE = Opcodes.IF_ICMPNE + ASM_OPCODE_DELTA;
171   static final int ASM_IF_ICMPLT = Opcodes.IF_ICMPLT + ASM_OPCODE_DELTA;
172   static final int ASM_IF_ICMPGE = Opcodes.IF_ICMPGE + ASM_OPCODE_DELTA;
173   static final int ASM_IF_ICMPGT = Opcodes.IF_ICMPGT + ASM_OPCODE_DELTA;
174   static final int ASM_IF_ICMPLE = Opcodes.IF_ICMPLE + ASM_OPCODE_DELTA;
175   static final int ASM_IF_ACMPEQ = Opcodes.IF_ACMPEQ + ASM_OPCODE_DELTA;
176   static final int ASM_IF_ACMPNE = Opcodes.IF_ACMPNE + ASM_OPCODE_DELTA;
177   static final int ASM_GOTO = Opcodes.GOTO + ASM_OPCODE_DELTA;
178   static final int ASM_JSR = Opcodes.JSR + ASM_OPCODE_DELTA;
179   static final int ASM_IFNULL = Opcodes.IFNULL + ASM_IFNULL_OPCODE_DELTA;
180   static final int ASM_IFNONNULL = Opcodes.IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
181   static final int ASM_GOTO_W = 220;
182 
Constants()183   private Constants() {}
184 
checkAsmExperimental(final Object caller)185   static void checkAsmExperimental(final Object caller) {
186     Class<?> callerClass = caller.getClass();
187     String internalName = callerClass.getName().replace('.', '/');
188     if (!isWhitelisted(internalName)) {
189       checkIsPreview(callerClass.getClassLoader().getResourceAsStream(internalName + ".class"));
190     }
191   }
192 
isWhitelisted(final String internalName)193   static boolean isWhitelisted(final String internalName) {
194     if (!internalName.startsWith("org/objectweb/asm/")) {
195       return false;
196     }
197     String member = "(Annotation|Class|Field|Method|Module|RecordComponent|Signature)";
198     return internalName.contains("Test$")
199         || Pattern.matches(
200             "org/objectweb/asm/util/Trace" + member + "Visitor(\\$.*)?", internalName)
201         || Pattern.matches(
202             "org/objectweb/asm/util/Check" + member + "Adapter(\\$.*)?", internalName);
203   }
204 
checkIsPreview(final InputStream classInputStream)205   static void checkIsPreview(final InputStream classInputStream) {
206     if (classInputStream == null) {
207       throw new IllegalStateException("Bytecode not available, can't check class version");
208     }
209     int minorVersion;
210     try (DataInputStream callerClassStream = new DataInputStream(classInputStream); ) {
211       callerClassStream.readInt();
212       minorVersion = callerClassStream.readUnsignedShort();
213     } catch (IOException ioe) {
214       throw new IllegalStateException("I/O error, can't check class version", ioe);
215     }
216     if (minorVersion != 0xFFFF) {
217       throw new IllegalStateException(
218           "ASM9_EXPERIMENTAL can only be used by classes compiled with --enable-preview");
219     }
220   }
221 }
222