1 /*
2 * Copyright (c) 2022, 2024, 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
32 import java.lang.classfile.constantpool.LoadableConstantEntry;
33 import java.lang.classfile.constantpool.PoolEntry;
34 import java.lang.classfile.constantpool.Utf8Entry;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.List;
38 import java.util.Objects;
39 import java.util.Optional;
40 import java.util.function.Function;
41
42 import static java.lang.classfile.constantpool.PoolEntry.*;
43
44 public final class ClassReaderImpl
45 implements ClassReader {
46 static final int CP_ITEM_START = 10;
47
48 private final byte[] buffer;
49 private final int metadataStart;
50 private final int classfileLength;
51 private final Function<Utf8Entry, AttributeMapper<?>> attributeMapper;
52 private final int flags;
53 private final int thisClassPos;
54 private ClassEntry thisClass;
55 private Optional<ClassEntry> superclass;
56 private final int constantPoolCount;
57 private final int[] cpOffset;
58
59 final ClassFileImpl context;
60 final int interfacesPos;
61 final PoolEntry[] cp;
62
63 private ClassModel containedClass;
64 private List<BootstrapMethodEntryImpl> bsmEntries;
65 private BootstrapMethodsAttribute bootstrapMethodsAttribute;
66
67 ClassReaderImpl(byte[] classfileBytes,
68 ClassFileImpl context) {
69 this.buffer = classfileBytes;
70 this.classfileLength = classfileBytes.length;
71 this.context = context;
72 this.attributeMapper = this.context.attributeMapper();
73 if (classfileLength < 4 || readInt(0) != 0xCAFEBABE) {
74 throw new IllegalArgumentException("Bad magic number");
75 }
76 if (readU2(6) > ClassFile.latestMajorVersion()) {
77 throw new IllegalArgumentException("Unsupported class file version: " + readU2(6));
78 }
79 int constantPoolCount = readU2(8);
80 int[] cpOffset = new int[constantPoolCount];
81 int p = CP_ITEM_START;
82 for (int i = 1; i < cpOffset.length; ++i) {
83 cpOffset[i] = p;
84 int tag = readU1(p);
85 ++p;
86 switch (tag) {
87 // 2
88 case TAG_CLASS, TAG_METHOD_TYPE, TAG_MODULE, TAG_STRING, TAG_PACKAGE -> p += 2;
89
90 // 3
91 case TAG_METHOD_HANDLE -> p += 3;
92
93 // 4
94 case TAG_DYNAMIC, TAG_FIELDREF, TAG_FLOAT, TAG_INTEGER,
95 TAG_INTERFACE_METHODREF, TAG_INVOKE_DYNAMIC, TAG_METHODREF,
96 TAG_NAME_AND_TYPE -> p += 4;
97
98 // 8
138 @Override
139 public ClassEntry thisClassEntry() {
140 if (thisClass == null) {
141 thisClass = readEntry(thisClassPos, ClassEntry.class);
142 }
143 return thisClass;
144 }
145
146 @Override
147 public Optional<ClassEntry> superclassEntry() {
148 if (superclass == null) {
149 superclass = Optional.ofNullable(readEntryOrNull(thisClassPos + 2, ClassEntry.class));
150 }
151 return superclass;
152 }
153
154 public int thisClassPos() {
155 return thisClassPos;
156 }
157
158 @Override
159 public int classfileLength() {
160 return classfileLength;
161 }
162
163 //------ Bootstrap Method Table handling
164
165 @Override
166 public int bootstrapMethodCount() {
167 return bootstrapMethodsAttribute().bootstrapMethodsSize();
168 }
169
170 @Override
171 public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) {
172 if (index < 0 || index >= bootstrapMethodCount()) {
173 throw new ConstantPoolException("Bad BSM index: " + index);
174 }
175 return bsmEntries().get(index);
176 }
177
|
1 /*
2 * Copyright (c) 2022, 2026, 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
32 import java.lang.classfile.constantpool.LoadableConstantEntry;
33 import java.lang.classfile.constantpool.PoolEntry;
34 import java.lang.classfile.constantpool.Utf8Entry;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.List;
38 import java.util.Objects;
39 import java.util.Optional;
40 import java.util.function.Function;
41
42 import static java.lang.classfile.constantpool.PoolEntry.*;
43
44 public final class ClassReaderImpl
45 implements ClassReader {
46 static final int CP_ITEM_START = 10;
47
48 private final byte[] buffer;
49 private final int metadataStart;
50 private final int classfileLength;
51 private final Function<Utf8Entry, AttributeMapper<?>> attributeMapper;
52 private final int version;
53 private final int flags;
54 private final int thisClassPos;
55 private ClassEntry thisClass;
56 private Optional<ClassEntry> superclass;
57 private final int constantPoolCount;
58 private final int[] cpOffset;
59
60 final ClassFileImpl context;
61 final int interfacesPos;
62 final PoolEntry[] cp;
63
64 private ClassModel containedClass;
65 private List<BootstrapMethodEntryImpl> bsmEntries;
66 private BootstrapMethodsAttribute bootstrapMethodsAttribute;
67
68 ClassReaderImpl(byte[] classfileBytes,
69 ClassFileImpl context) {
70 this.buffer = classfileBytes;
71 this.classfileLength = classfileBytes.length;
72 this.context = context;
73 this.attributeMapper = this.context.attributeMapper();
74 if (classfileLength < 4 || readInt(0) != 0xCAFEBABE) {
75 throw new IllegalArgumentException("Bad magic number");
76 }
77 int version = readInt(4);
78 if ((version & 0xFFFF) > ClassFile.latestMajorVersion()) {
79 throw new IllegalArgumentException("Unsupported class file version: " + version);
80 }
81 this.version = version;
82 int constantPoolCount = readU2(8);
83 int[] cpOffset = new int[constantPoolCount];
84 int p = CP_ITEM_START;
85 for (int i = 1; i < cpOffset.length; ++i) {
86 cpOffset[i] = p;
87 int tag = readU1(p);
88 ++p;
89 switch (tag) {
90 // 2
91 case TAG_CLASS, TAG_METHOD_TYPE, TAG_MODULE, TAG_STRING, TAG_PACKAGE -> p += 2;
92
93 // 3
94 case TAG_METHOD_HANDLE -> p += 3;
95
96 // 4
97 case TAG_DYNAMIC, TAG_FIELDREF, TAG_FLOAT, TAG_INTEGER,
98 TAG_INTERFACE_METHODREF, TAG_INVOKE_DYNAMIC, TAG_METHODREF,
99 TAG_NAME_AND_TYPE -> p += 4;
100
101 // 8
141 @Override
142 public ClassEntry thisClassEntry() {
143 if (thisClass == null) {
144 thisClass = readEntry(thisClassPos, ClassEntry.class);
145 }
146 return thisClass;
147 }
148
149 @Override
150 public Optional<ClassEntry> superclassEntry() {
151 if (superclass == null) {
152 superclass = Optional.ofNullable(readEntryOrNull(thisClassPos + 2, ClassEntry.class));
153 }
154 return superclass;
155 }
156
157 public int thisClassPos() {
158 return thisClassPos;
159 }
160
161 public int classFileVersion() {
162 return version;
163 }
164
165 @Override
166 public int classfileLength() {
167 return classfileLength;
168 }
169
170 //------ Bootstrap Method Table handling
171
172 @Override
173 public int bootstrapMethodCount() {
174 return bootstrapMethodsAttribute().bootstrapMethodsSize();
175 }
176
177 @Override
178 public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) {
179 if (index < 0 || index >= bootstrapMethodCount()) {
180 throw new ConstantPoolException("Bad BSM index: " + index);
181 }
182 return bsmEntries().get(index);
183 }
184
|