mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-06 14:10:36 +00:00
8297777: Convert jdk.jlink StringSharingPlugin to use Class File API
Reviewed-by: asotona
This commit is contained in:
parent
bf63945ad1
commit
e29f0c2d75
@ -24,20 +24,9 @@
|
||||
*/
|
||||
package jdk.tools.jlink.internal.plugins;
|
||||
|
||||
import com.sun.tools.classfile.Annotation;
|
||||
import com.sun.tools.classfile.Attribute;
|
||||
import com.sun.tools.classfile.Attributes;
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.ConstantPool;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
import com.sun.tools.classfile.Field;
|
||||
import com.sun.tools.classfile.LocalVariableTable_attribute;
|
||||
import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
|
||||
import com.sun.tools.classfile.Method;
|
||||
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
|
||||
import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute;
|
||||
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
|
||||
import com.sun.tools.classfile.Signature_attribute;
|
||||
import jdk.internal.classfile.*;
|
||||
import jdk.internal.classfile.attribute.*;
|
||||
import jdk.internal.classfile.constantpool.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
@ -80,10 +69,10 @@ public class StringSharingPlugin extends AbstractPlugin implements ResourcePrevi
|
||||
|
||||
private static final class DescriptorsScanner {
|
||||
|
||||
private final ClassFile cf;
|
||||
private final ClassModel cm;
|
||||
|
||||
private DescriptorsScanner(ClassFile cf) {
|
||||
this.cf = cf;
|
||||
private DescriptorsScanner(ClassModel cm) {
|
||||
this.cm = cm;
|
||||
}
|
||||
|
||||
private Set<Integer> scan() throws Exception {
|
||||
@ -94,130 +83,109 @@ public class StringSharingPlugin extends AbstractPlugin implements ResourcePrevi
|
||||
|
||||
scanMethods(utf8Descriptors);
|
||||
|
||||
scanAttributes(cf.attributes, utf8Descriptors);
|
||||
scanAttributes(cm.attributes(), utf8Descriptors);
|
||||
|
||||
return utf8Descriptors;
|
||||
}
|
||||
|
||||
private void scanAttributes(Attributes attributes,
|
||||
private void scanAttributes(List<Attribute<?>> attributes,
|
||||
Set<Integer> utf8Descriptors) throws Exception {
|
||||
for (Attribute a : attributes) {
|
||||
if (a instanceof Signature_attribute) {
|
||||
Signature_attribute sig = (Signature_attribute) a;
|
||||
utf8Descriptors.add(sig.signature_index);
|
||||
} else if (a instanceof RuntimeVisibleAnnotations_attribute) {
|
||||
RuntimeVisibleAnnotations_attribute an
|
||||
= (RuntimeVisibleAnnotations_attribute) a;
|
||||
for (Annotation annotation : an.annotations) {
|
||||
scanAnnotation(annotation, utf8Descriptors);
|
||||
for (Attribute<?> a : attributes) {
|
||||
switch (a) {
|
||||
case SignatureAttribute sig -> {
|
||||
utf8Descriptors.add(sig.signature().index());
|
||||
}
|
||||
} else if (a instanceof RuntimeInvisibleAnnotations_attribute) {
|
||||
RuntimeInvisibleAnnotations_attribute an
|
||||
= (RuntimeInvisibleAnnotations_attribute) a;
|
||||
for (Annotation annotation : an.annotations) {
|
||||
scanAnnotation(annotation, utf8Descriptors);
|
||||
case RuntimeVisibleAnnotationsAttribute an -> {
|
||||
for (Annotation annotation : an.annotations())
|
||||
scanAnnotation(annotation, utf8Descriptors);
|
||||
}
|
||||
} else if (a instanceof RuntimeParameterAnnotations_attribute) {
|
||||
RuntimeParameterAnnotations_attribute rap
|
||||
= (RuntimeParameterAnnotations_attribute) a;
|
||||
for (Annotation[] arr : rap.parameter_annotations) {
|
||||
for (Annotation an : arr) {
|
||||
scanAnnotation(an, utf8Descriptors);
|
||||
case RuntimeInvisibleAnnotationsAttribute an -> {
|
||||
for (Annotation annotation : an.annotations())
|
||||
scanAnnotation(annotation, utf8Descriptors);
|
||||
}
|
||||
case RuntimeVisibleParameterAnnotationsAttribute rap -> {
|
||||
for (List<Annotation> arr : rap.parameterAnnotations()) {
|
||||
for (Annotation an : arr)
|
||||
scanAnnotation(an, utf8Descriptors);
|
||||
}
|
||||
}
|
||||
} else if (a instanceof LocalVariableTable_attribute) {
|
||||
LocalVariableTable_attribute lvt
|
||||
= (LocalVariableTable_attribute) a;
|
||||
for (LocalVariableTable_attribute.Entry entry
|
||||
: lvt.local_variable_table) {
|
||||
utf8Descriptors.add(entry.descriptor_index);
|
||||
case RuntimeInvisibleParameterAnnotationsAttribute rap -> {
|
||||
for (List<Annotation> arr : rap.parameterAnnotations()) {
|
||||
for (Annotation an : arr)
|
||||
scanAnnotation(an, utf8Descriptors);
|
||||
}
|
||||
}
|
||||
} else if (a instanceof LocalVariableTypeTable_attribute) {
|
||||
LocalVariableTypeTable_attribute lvt
|
||||
= (LocalVariableTypeTable_attribute) a;
|
||||
for (LocalVariableTypeTable_attribute.Entry entry
|
||||
: lvt.local_variable_table) {
|
||||
utf8Descriptors.add(entry.signature_index);
|
||||
case LocalVariableTableAttribute lvt -> {
|
||||
for (LocalVariableInfo entry: lvt.localVariables())
|
||||
utf8Descriptors.add(entry.name().index());
|
||||
}
|
||||
case LocalVariableTypeTableAttribute lvt -> {
|
||||
for (LocalVariableTypeInfo entry: lvt.localVariableTypes())
|
||||
utf8Descriptors.add(entry.signature().index());
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanAnnotation(Annotation annotation,
|
||||
Set<Integer> utf8Descriptors) throws Exception {
|
||||
utf8Descriptors.add(annotation.type_index);
|
||||
for (Annotation.element_value_pair evp : annotation.element_value_pairs) {
|
||||
utf8Descriptors.add(evp.element_name_index);
|
||||
scanElementValue(evp.value, utf8Descriptors);
|
||||
utf8Descriptors.add(annotation.className().index());
|
||||
for (AnnotationElement evp : annotation.elements()) {
|
||||
utf8Descriptors.add(evp.name().index());
|
||||
scanElementValue(evp.value(), utf8Descriptors);
|
||||
}
|
||||
}
|
||||
|
||||
private void scanElementValue(Annotation.element_value value,
|
||||
private void scanElementValue(AnnotationValue value,
|
||||
Set<Integer> utf8Descriptors) throws Exception {
|
||||
if (value instanceof Annotation.Enum_element_value) {
|
||||
Annotation.Enum_element_value eev
|
||||
= (Annotation.Enum_element_value) value;
|
||||
utf8Descriptors.add(eev.type_name_index);
|
||||
}
|
||||
if (value instanceof Annotation.Class_element_value) {
|
||||
Annotation.Class_element_value eev
|
||||
= (Annotation.Class_element_value) value;
|
||||
utf8Descriptors.add(eev.class_info_index);
|
||||
}
|
||||
if (value instanceof Annotation.Annotation_element_value) {
|
||||
Annotation.Annotation_element_value aev
|
||||
= (Annotation.Annotation_element_value) value;
|
||||
scanAnnotation(aev.annotation_value, utf8Descriptors);
|
||||
}
|
||||
if (value instanceof Annotation.Array_element_value) {
|
||||
Annotation.Array_element_value aev
|
||||
= (Annotation.Array_element_value) value;
|
||||
for (Annotation.element_value v : aev.values) {
|
||||
scanElementValue(v, utf8Descriptors);
|
||||
switch (value) {
|
||||
case AnnotationValue.OfEnum eev ->
|
||||
utf8Descriptors.add(eev.className().index());
|
||||
case AnnotationValue.OfClass eev ->
|
||||
utf8Descriptors.add(eev.className().index());
|
||||
case AnnotationValue.OfAnnotation aev ->
|
||||
scanAnnotation(aev.annotation(), utf8Descriptors);
|
||||
case AnnotationValue.OfArray aev -> {
|
||||
for (AnnotationValue v : aev.values())
|
||||
scanElementValue(v, utf8Descriptors);
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanFields(Set<Integer> utf8Descriptors)
|
||||
throws Exception {
|
||||
for (Field field : cf.fields) {
|
||||
int descriptorIndex = field.descriptor.index;
|
||||
for (FieldModel field : cm.fields()) {
|
||||
int descriptorIndex = field.fieldType().index();
|
||||
utf8Descriptors.add(descriptorIndex);
|
||||
scanAttributes(field.attributes, utf8Descriptors);
|
||||
scanAttributes(field.attributes(), utf8Descriptors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void scanMethods(Set<Integer> utf8Descriptors)
|
||||
throws Exception {
|
||||
for (Method m : cf.methods) {
|
||||
int descriptorIndex = m.descriptor.index;
|
||||
for (MethodModel m : cm.methods()) {
|
||||
int descriptorIndex = m.methodType().index();
|
||||
utf8Descriptors.add(descriptorIndex);
|
||||
scanAttributes(m.attributes, utf8Descriptors);
|
||||
scanAttributes(m.attributes(), utf8Descriptors);
|
||||
}
|
||||
}
|
||||
|
||||
private void scanConstantPool(Set<Integer> utf8Descriptors)
|
||||
throws Exception {
|
||||
for (int i = 1; i < cf.constant_pool.size(); i++) {
|
||||
for (int i = 1; i < cm.constantPool().entryCount(); i += cm.constantPool().entryByIndex(i).width()) {
|
||||
try {
|
||||
ConstantPool.CPInfo info = cf.constant_pool.get(i);
|
||||
if (info instanceof ConstantPool.CONSTANT_NameAndType_info) {
|
||||
ConstantPool.CONSTANT_NameAndType_info nameAndType
|
||||
= (ConstantPool.CONSTANT_NameAndType_info) info;
|
||||
utf8Descriptors.add(nameAndType.type_index);
|
||||
PoolEntry info = cm.constantPool().entryByIndex(i);
|
||||
switch (info) {
|
||||
case NameAndTypeEntry nameAndType ->
|
||||
utf8Descriptors.add(nameAndType.type().index());
|
||||
case MethodTypeEntry mt ->
|
||||
utf8Descriptors.add(mt.descriptor().index());
|
||||
default -> {}
|
||||
}
|
||||
if (info instanceof ConstantPool.CONSTANT_MethodType_info) {
|
||||
ConstantPool.CONSTANT_MethodType_info mt
|
||||
= (ConstantPool.CONSTANT_MethodType_info) info;
|
||||
utf8Descriptors.add(mt.descriptor_index);
|
||||
}
|
||||
|
||||
if (info instanceof ConstantPool.CONSTANT_Double_info
|
||||
|| info instanceof ConstantPool.CONSTANT_Long_info) {
|
||||
i++;
|
||||
}
|
||||
} catch (ConstantPool.InvalidIndex ex) {
|
||||
} catch (ConstantPoolException ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
@ -227,13 +195,7 @@ public class StringSharingPlugin extends AbstractPlugin implements ResourcePrevi
|
||||
public byte[] transform(ResourcePoolEntry resource, ResourcePoolBuilder out,
|
||||
StringTable strings) throws IOException, Exception {
|
||||
byte[] content = resource.contentBytes();
|
||||
ClassFile cf;
|
||||
try (InputStream stream = new ByteArrayInputStream(content)) {
|
||||
cf = ClassFile.read(stream);
|
||||
} catch (ConstantPoolException ex) {
|
||||
throw new IOException("Compressor EX " + ex + " for "
|
||||
+ resource.path() + " content.length " + content.length, ex);
|
||||
}
|
||||
ClassModel cf = Classfile.of().parse(content);
|
||||
DescriptorsScanner scanner = new DescriptorsScanner(cf);
|
||||
return optimize(resource, out, strings, scanner.scan(), content);
|
||||
}
|
||||
@ -254,16 +216,14 @@ public class StringSharingPlugin extends AbstractPlugin implements ResourcePrevi
|
||||
int tag = stream.readUnsignedByte();
|
||||
byte[] arr;
|
||||
switch (tag) {
|
||||
case ConstantPool.CONSTANT_Utf8: {
|
||||
case Classfile.TAG_UTF8: {
|
||||
String original = stream.readUTF();
|
||||
// 2 cases, a Descriptor or a simple String
|
||||
if (descriptorIndexes.contains(i)) {
|
||||
SignatureParser.ParseResult parseResult
|
||||
= SignatureParser.parseSignatureDescriptor(original);
|
||||
List<Integer> indexes
|
||||
= parseResult.types.stream().map((type) -> {
|
||||
return strings.addString(type);
|
||||
}).toList();
|
||||
= parseResult.types.stream().map(strings::addString).toList();
|
||||
if (!indexes.isEmpty()) {
|
||||
out.write(StringSharingDecompressor.EXTERNALIZED_STRING_DESCRIPTOR);
|
||||
int sigIndex = strings.addString(parseResult.formatted);
|
||||
@ -280,11 +240,9 @@ public class StringSharingPlugin extends AbstractPlugin implements ResourcePrevi
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ConstantPool.CONSTANT_Long:
|
||||
case ConstantPool.CONSTANT_Double: {
|
||||
case Classfile.TAG_LONG:
|
||||
case Classfile.TAG_DOUBLE:
|
||||
i++;
|
||||
}
|
||||
default: {
|
||||
out.write(tag);
|
||||
int size = SIZES[tag];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user