< prev index next >

src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java

Print this page

  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 
< prev index next >