diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bb5f97de..d047b933 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,8 +11,8 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
- # Always test on the latest version and LTS.
- java: [8, 11, 17, 21, 25]
+ # Requires Java 25 for the Class-File API (java.lang.classfile)
+ java: [25]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
diff --git a/pom.xml b/pom.xml
index 7834774e..6290c83d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,13 +7,12 @@
UTF-8
UTF-8
- 8
- 8
- 8
+ 25
+ 25
+ 25
3.9.6
${project.build.directory}/test-working-directory
- 9.9.1
4.0.0
org.vafer
@@ -79,31 +78,6 @@
commons-io
2.21.0
-
- org.ow2.asm
- asm
- ${asm.version}
-
-
- org.ow2.asm
- asm-analysis
- ${asm.version}
-
-
- org.ow2.asm
- asm-commons
- ${asm.version}
-
-
- org.ow2.asm
- asm-util
- ${asm.version}
-
-
- org.ow2.asm
- asm-tree
- ${asm.version}
-
@@ -250,7 +224,7 @@
shade
- true
+ false
*:*
@@ -264,11 +238,6 @@
commons-io:commons-io
- org.ow2.asm:asm
- org.ow2.asm:asm-analysis
- org.ow2.asm:asm-commons
- org.ow2.asm:asm-util
- org.ow2.asm:asm-tree
@@ -276,15 +245,6 @@
org.apache.commons
org.vafer.jdeb.shaded.commons
-
- org.ow2.asm
- org.vafer.jdeb.shaded.ow2.asm
-
-
- org.objectweb.asm
- org.vafer.jdeb.shaded.objectweb.asm
-
diff --git a/src/main/java/org/vafer/jdependency/Clazzpath.java b/src/main/java/org/vafer/jdependency/Clazzpath.java
index 29310f1b..b09db71c 100644
--- a/src/main/java/org/vafer/jdependency/Clazzpath.java
+++ b/src/main/java/org/vafer/jdependency/Clazzpath.java
@@ -31,8 +31,6 @@
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
-import org.apache.commons.io.input.MessageDigestInputStream;
-import org.objectweb.asm.ClassReader;
import static org.apache.commons.io.FilenameUtils.normalize;
import static org.apache.commons.io.FilenameUtils.separatorsToUnix;
@@ -165,16 +163,15 @@ private ClazzpathUnit addClazzpathUnit( final Iterable resources, fina
// extract dependencies of clazz
InputStream inputStream = resource.getInputStream();
try {
- final MessageDigest digest = MessageDigest.getInstance("SHA-256");
- final MessageDigestInputStream calculatingInputStream =
- MessageDigestInputStream.builder().setInputStream(inputStream).setMessageDigest(digest).get();
+ final byte[] classBytes = inputStream.readAllBytes();
+ final MessageDigest digest = MessageDigest.getInstance("SHA-256");
if (versions) {
- inputStream = calculatingInputStream;
+ digest.update(classBytes);
}
final DependenciesClassAdapter v = new DependenciesClassAdapter();
- new ClassReader(inputStream).accept(v, ClassReader.EXPAND_FRAMES | ClassReader.SKIP_DEBUG);
+ v.accept(classBytes);
// get or create clazz
final String clazzName = resource.name;
diff --git a/src/main/java/org/vafer/jdependency/asm/DependenciesClassAdapter.java b/src/main/java/org/vafer/jdependency/asm/DependenciesClassAdapter.java
index 4085716f..ce1b29cd 100644
--- a/src/main/java/org/vafer/jdependency/asm/DependenciesClassAdapter.java
+++ b/src/main/java/org/vafer/jdependency/asm/DependenciesClassAdapter.java
@@ -15,166 +15,51 @@
*/
package org.vafer.jdependency.asm;
+import java.lang.classfile.ClassFile;
+import java.lang.classfile.ClassModel;
+import java.lang.classfile.constantpool.ClassEntry;
+import java.lang.classfile.constantpool.PoolEntry;
+import java.lang.classfile.constantpool.Utf8Entry;
import java.util.HashSet;
import java.util.Set;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.ModuleVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.RecordComponentVisitor;
-import org.objectweb.asm.TypePath;
-import org.objectweb.asm.commons.ClassRemapper;
-import org.objectweb.asm.commons.Remapper;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* internal - do not use
*/
-
-public final class DependenciesClassAdapter extends ClassRemapper {
-
- private static final int OPCODES = Opcodes.ASM9;
-
- private static final EmptyVisitor ev = new EmptyVisitor();
-
- public DependenciesClassAdapter() {
- super(ev, new CollectingRemapper());
- }
-
- public Set getDependencies() {
- return ((CollectingRemapper) super.remapper).classes;
- }
-
- private static class CollectingRemapper extends Remapper {
-
- final Set classes = new HashSet();
-
- public String map(String pClassName) {
- classes.add(pClassName.replace('/', '.'));
- return pClassName;
- }
- }
-
- static class EmptyVisitor extends ClassVisitor {
-
- private static final AnnotationVisitor av = new AnnotationVisitor(OPCODES) {
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- return this;
- }
-
- @Override
- public AnnotationVisitor visitArray(String name) {
- return this;
- }
- };
-
- private static final MethodVisitor mv = new MethodVisitor(OPCODES) {
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- return av;
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- return av;
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(
- int parameter, String desc, boolean visible) {
- return av;
- }
-
- @Override
- public AnnotationVisitor visitInsnAnnotation( int typeRef, TypePath typePath, String descriptor,
- boolean visible ) {
- return av;
- }
-
- @Override
- public AnnotationVisitor visitLocalVariableAnnotation( int typeRef, TypePath typePath, Label[] start,
- Label[] end, int[] index, String descriptor,
- boolean visible ) {
- return av;
- }
-
- @Override
- public AnnotationVisitor visitTryCatchAnnotation( int typeRef, TypePath typePath, String descriptor,
- boolean visible ) {
- return av;
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation( int typeRef, TypePath typePath, String descriptor,
- boolean visible ) {
- return av;
- }
- };
-
- private static final FieldVisitor fieldVisitor = new FieldVisitor(OPCODES) {
- @Override
- public AnnotationVisitor visitAnnotation( String desc, boolean visible ) {
- return av;
+public final class DependenciesClassAdapter {
+
+ private static final Pattern DESCRIPTOR_PATTERN = Pattern.compile("L([a-zA-Z0-9_/\\$]+);");
+
+ private final Set classes = new HashSet<>();
+
+ public void accept(byte[] classBytes) {
+ ClassModel cm = ClassFile.of().parse(classBytes);
+ for (PoolEntry pe : cm.constantPool()) {
+ if (pe instanceof ClassEntry ce) {
+ String name = ce.asInternalName();
+ if (name.startsWith("[")) {
+ Matcher m = DESCRIPTOR_PATTERN.matcher(name);
+ while (m.find()) {
+ classes.add(m.group(1).replace('/', '.'));
+ }
+ } else {
+ classes.add(name.replace('/', '.'));
+ }
+ } else if (pe instanceof Utf8Entry ue) {
+ String str = ue.stringValue();
+ if (str.indexOf('L') != -1 && str.indexOf(';') != -1) {
+ Matcher m = DESCRIPTOR_PATTERN.matcher(str);
+ while (m.find()) {
+ classes.add(m.group(1).replace('/', '.'));
+ }
+ }
}
- @Override
- public AnnotationVisitor visitTypeAnnotation( int typeRef, TypePath typePath, String descriptor,
- boolean visible ) {
- return av;
- }
- };
-
- private static final ModuleVisitor moduleVisitor = new ModuleVisitor(OPCODES) {
- };
-
- private static final RecordComponentVisitor recordComponentVisitor = new RecordComponentVisitor(OPCODES) {
- @Override
- public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
- return av;
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
- return av;
- }
- };
-
- public EmptyVisitor() {
- super(OPCODES);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- return av;
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
- return fieldVisitor;
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- return mv;
- }
-
- @Override
- public AnnotationVisitor visitTypeAnnotation( int typeRef, TypePath typePath, String descriptor,
- boolean visible ) {
- return av;
- }
-
- @Override
- public ModuleVisitor visitModule(String name, int access, String version) {
- return moduleVisitor;
}
+ }
- @Override
- public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) {
- return recordComponentVisitor;
- }
+ public Set getDependencies() {
+ return classes;
}
}
diff --git a/src/main/java/org/vafer/jdependency/utils/DependencyUtils.java b/src/main/java/org/vafer/jdependency/utils/DependencyUtils.java
index efc7b912..97bf8784 100644
--- a/src/main/java/org/vafer/jdependency/utils/DependencyUtils.java
+++ b/src/main/java/org/vafer/jdependency/utils/DependencyUtils.java
@@ -19,7 +19,6 @@
import java.io.InputStream;
import java.util.Set;
-import org.objectweb.asm.ClassReader;
import org.vafer.jdependency.asm.DependenciesClassAdapter;
/**
@@ -70,7 +69,7 @@ public static Set getDependenciesOfJar( final InputStream pInputStream )
public static Set getDependenciesOfClass( final InputStream pInputStream ) throws IOException {
final DependenciesClassAdapter v = new DependenciesClassAdapter();
- new ClassReader( pInputStream ).accept( v, ClassReader.EXPAND_FRAMES );
+ v.accept(pInputStream.readAllBytes());
final Set depNames = v.getDependencies();
return depNames;
}