8331855: Convert jdk.jdeps jdeprscan and jdeps to use the Classfile API
Reviewed-by: asotona
This commit is contained in:
parent
beeffd4671
commit
d4c2edf2c9
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,16 +25,13 @@
|
||||
|
||||
package com.sun.tools.jdeprscan.scan;
|
||||
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.lang.classfile.constantpool.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.ConstantPool;
|
||||
|
||||
import static com.sun.tools.classfile.ConstantPool.CPInfo;
|
||||
|
||||
/**
|
||||
* A container for selected constant pool entries. There are currently
|
||||
* lists that contain the following types of CP entries:
|
||||
@ -45,15 +42,21 @@ import static com.sun.tools.classfile.ConstantPool.CPInfo;
|
||||
* - CONSTANT_InterfaceMethodref_info
|
||||
*/
|
||||
class CPEntries {
|
||||
final List<ConstantPool.CONSTANT_Class_info> classes = new ArrayList<>();
|
||||
final List<ConstantPool.CONSTANT_Fieldref_info> fieldRefs = new ArrayList<>();
|
||||
final List<ConstantPool.CONSTANT_Methodref_info> methodRefs = new ArrayList<>();
|
||||
final List<ConstantPool.CONSTANT_InterfaceMethodref_info> intfMethodRefs = new ArrayList<>();
|
||||
final List<ClassEntry> classes = new ArrayList<>();
|
||||
final List<FieldRefEntry> fieldRefs = new ArrayList<>();
|
||||
final List<MethodRefEntry> methodRefs = new ArrayList<>();
|
||||
final List<InterfaceMethodRefEntry> intfMethodRefs = new ArrayList<>();
|
||||
|
||||
public static CPEntries loadFrom(ClassFile cf) {
|
||||
public static CPEntries loadFrom(ClassModel cf) {
|
||||
CPEntries entries = new CPEntries();
|
||||
for (CPInfo cpi : cf.constant_pool.entries()) {
|
||||
cpi.accept(new CPSelector(), entries);
|
||||
for (PoolEntry cpi : cf.constantPool()) {
|
||||
switch (cpi) {
|
||||
case ClassEntry ce -> entries.classes.add(ce);
|
||||
case MethodRefEntry mref -> entries.methodRefs.add(mref);
|
||||
case InterfaceMethodRefEntry imref -> entries.intfMethodRefs.add(imref);
|
||||
case FieldRefEntry fref -> entries.fieldRefs.add(fref);
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.jdeprscan.scan;
|
||||
|
||||
import com.sun.tools.classfile.ConstantPool;
|
||||
import com.sun.tools.classfile.ConstantPool.CONSTANT_Dynamic_info;
|
||||
|
||||
/**
|
||||
* A visitor that selects constant pool entries by type and adds
|
||||
* them to the given CPEntries object.
|
||||
*/
|
||||
class CPSelector implements ConstantPool.Visitor<Void,CPEntries> {
|
||||
@Override
|
||||
public Void visitClass(ConstantPool.CONSTANT_Class_info info, CPEntries p) {
|
||||
p.classes.add(info);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDouble(ConstantPool.CONSTANT_Double_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFieldref(ConstantPool.CONSTANT_Fieldref_info info, CPEntries p) {
|
||||
p.fieldRefs.add(info);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFloat(ConstantPool.CONSTANT_Float_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInteger(ConstantPool.CONSTANT_Integer_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInterfaceMethodref(ConstantPool.CONSTANT_InterfaceMethodref_info info, CPEntries p) {
|
||||
p.intfMethodRefs.add(info);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitInvokeDynamic(ConstantPool.CONSTANT_InvokeDynamic_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitDynamicConstant(CONSTANT_Dynamic_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitLong(ConstantPool.CONSTANT_Long_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMethodref(ConstantPool.CONSTANT_Methodref_info info, CPEntries p) {
|
||||
p.methodRefs.add(info);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMethodHandle(ConstantPool.CONSTANT_MethodHandle_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMethodType(ConstantPool.CONSTANT_MethodType_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitModule(ConstantPool.CONSTANT_Module_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNameAndType(ConstantPool.CONSTANT_NameAndType_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPackage(ConstantPool.CONSTANT_Package_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitString(ConstantPool.CONSTANT_String_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitUtf8(ConstantPool.CONSTANT_Utf8_info info, CPEntries p) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,10 +25,9 @@
|
||||
|
||||
package com.sun.tools.jdeprscan.scan;
|
||||
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
@ -92,9 +91,9 @@ public class ClassFinder {
|
||||
* @param className the class to search for
|
||||
* @return a ClassFile instance, or null if not found
|
||||
*/
|
||||
public ClassFile find(String className) {
|
||||
public ClassModel find(String className) {
|
||||
for (PathEntry pe : list) {
|
||||
ClassFile cf = pe.find(className);
|
||||
ClassModel cf = pe.find(className);
|
||||
if (cf != null) {
|
||||
return cf;
|
||||
}
|
||||
@ -113,7 +112,7 @@ public class ClassFinder {
|
||||
* @param className the class to search for
|
||||
* @return a ClassFile instance, or null if not found
|
||||
*/
|
||||
ClassFile find(String className);
|
||||
ClassModel find(String className);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,14 +126,14 @@ public class ClassFinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassFile find(String className) {
|
||||
public ClassModel find(String className) {
|
||||
JarEntry entry = jarFile.getJarEntry(className + ".class");
|
||||
if (entry == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return ClassFile.read(jarFile.getInputStream(entry));
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
return ClassFile.of().parse(jarFile.getInputStream(entry).readAllBytes());
|
||||
} catch (IOException | IllegalArgumentException ex) {
|
||||
if (verbose) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
@ -154,13 +153,13 @@ public class ClassFinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassFile find(String className) {
|
||||
public ClassModel find(String className) {
|
||||
Path classFileName = dir.resolve(className + ".class");
|
||||
try {
|
||||
return ClassFile.read(classFileName);
|
||||
return ClassFile.of().parse(classFileName);
|
||||
} catch (NoSuchFileException nsfe) {
|
||||
// not found, return silently
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
} catch (IOException | IllegalArgumentException ex) {
|
||||
if (verbose) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
@ -181,7 +180,7 @@ public class ClassFinder {
|
||||
final FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
|
||||
|
||||
@Override
|
||||
public ClassFile find(String className) {
|
||||
public ClassModel find(String className) {
|
||||
int end = className.lastIndexOf('/');
|
||||
if (end < 0) {
|
||||
return null;
|
||||
@ -194,13 +193,13 @@ public class ClassFinder {
|
||||
.filter(Files::exists)
|
||||
.findFirst();
|
||||
if (opath.isPresent()) {
|
||||
return ClassFile.read(opath.get());
|
||||
return ClassFile.of().parse(opath.get());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (NoSuchFileException nsfe) {
|
||||
// not found, return silently
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
} catch (IOException | IllegalArgumentException ex) {
|
||||
if (verbose) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.jdeprscan.scan;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a method's signature, that is, its parameter types
|
||||
* and its return type.
|
||||
*/
|
||||
public class MethodSig {
|
||||
final List<String> parameters;
|
||||
final String returnType;
|
||||
|
||||
/**
|
||||
* Parses the method descriptor and returns a MethodSig instance.
|
||||
*
|
||||
* @param desc the descriptor to parse
|
||||
* @return the new MethodSig instance
|
||||
*/
|
||||
public static MethodSig fromDesc(String desc) {
|
||||
return parse(desc, 0, desc.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this method's return type.
|
||||
*
|
||||
* @return the return type
|
||||
*/
|
||||
public String getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of parameters of this method.
|
||||
*
|
||||
* @return the parameter list
|
||||
*/
|
||||
public List<String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string describing this method.
|
||||
*
|
||||
* @return the string description
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("parameters");
|
||||
if (parameters.isEmpty()) {
|
||||
sb.append(" none");
|
||||
} else {
|
||||
int i = 0;
|
||||
for (String p : parameters) {
|
||||
sb.append(String.format(" %d=%s", i++, p));
|
||||
}
|
||||
}
|
||||
sb.append(String.format(" return %s", returnType));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private MethodSig(List<String> parameters, String returnType) {
|
||||
this.parameters = Collections.unmodifiableList(parameters);
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
private static IllegalArgumentException ex(String desc, int pos) {
|
||||
return new IllegalArgumentException(String.format(
|
||||
"illegal descriptor \"%s\" at position %d", desc, pos));
|
||||
}
|
||||
|
||||
private static MethodSig parse(String desc, int start, int end)
|
||||
throws IllegalArgumentException {
|
||||
int p = start;
|
||||
int dims = 0;
|
||||
boolean inReturnType = false;
|
||||
String returnType = null;
|
||||
List<String> parameters = new ArrayList<>();
|
||||
|
||||
while (p < end) {
|
||||
String type;
|
||||
char ch;
|
||||
switch (ch = desc.charAt(p)) {
|
||||
case '(':
|
||||
p++;
|
||||
continue;
|
||||
|
||||
case ')':
|
||||
p++;
|
||||
inReturnType = true;
|
||||
continue;
|
||||
|
||||
case '[':
|
||||
p++;
|
||||
dims++;
|
||||
continue;
|
||||
|
||||
case 'B': // byte
|
||||
case 'C': // char
|
||||
case 'D': // double
|
||||
case 'F': // float
|
||||
case 'I': // int
|
||||
case 'J': // long
|
||||
case 'S': // short
|
||||
case 'Z': // boolean
|
||||
case 'V': // void
|
||||
type = Character.toString(ch);
|
||||
p++;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
int sep = desc.indexOf(';', p);
|
||||
if (sep == -1 || sep >= end)
|
||||
throw ex(desc, p);
|
||||
type = desc.substring(p, ++sep);
|
||||
p = sep;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ex(desc, p);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for ( ; dims > 0; dims-- )
|
||||
sb.append("[");
|
||||
sb.append(type);
|
||||
if (inReturnType) {
|
||||
returnType = sb.toString();
|
||||
} else {
|
||||
parameters.add(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (returnType == null) {
|
||||
throw ex(desc, end);
|
||||
}
|
||||
|
||||
return new MethodSig(parameters, returnType);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,13 @@ package com.sun.tools.jdeprscan.scan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.classfile.AccessFlags;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.lang.classfile.constantpool.FieldRefEntry;
|
||||
import java.lang.classfile.constantpool.NameAndTypeEntry;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.reflect.AccessFlag;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
@ -41,17 +48,12 @@ import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
import com.sun.tools.jdeprscan.DeprData;
|
||||
import com.sun.tools.jdeprscan.DeprDB;
|
||||
import com.sun.tools.jdeprscan.Messages;
|
||||
|
||||
import static com.sun.tools.classfile.AccessFlags.*;
|
||||
import static com.sun.tools.classfile.ConstantPool.*;
|
||||
|
||||
/**
|
||||
* An object that represents the scanning phase of deprecation usage checking.
|
||||
* Given a deprecation database, scans the targeted directory hierarchy, jar
|
||||
@ -85,7 +87,7 @@ public class Scan {
|
||||
// one, we should instead add a reference to the symbol file for that release instead
|
||||
// of the current image. The problems are a) it's unclear how to get from a release
|
||||
// to paths that reference the symbol files, as this might be internal to the file
|
||||
// manager; and b) the symbol file includes .sig files, not class files, which ClassFile
|
||||
// manager; and b) the symbol file includes .sig files, not class files, which ClassModel
|
||||
// might not be able to handle.
|
||||
f.addJrt();
|
||||
|
||||
@ -164,13 +166,13 @@ public class Scan {
|
||||
|
||||
Pattern refTypePattern = Pattern.compile("\\[+L(.*);");
|
||||
|
||||
String typeKind(ClassFile cf) {
|
||||
AccessFlags flags = cf.access_flags;
|
||||
if (flags.is(ACC_ENUM)) {
|
||||
String typeKind(ClassModel cf) {
|
||||
AccessFlags flags = cf.flags();
|
||||
if (flags.has(AccessFlag.ENUM)) {
|
||||
return "enum";
|
||||
} else if (flags.is(ACC_ANNOTATION)) {
|
||||
} else if (flags.has(AccessFlag.ANNOTATION)) {
|
||||
return "@interface";
|
||||
} else if (flags.is(ACC_INTERFACE)) {
|
||||
} else if (flags.has(AccessFlag.INTERFACE)) {
|
||||
return "interface";
|
||||
} else {
|
||||
return "class";
|
||||
@ -181,44 +183,43 @@ public class Scan {
|
||||
return Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
|
||||
}
|
||||
|
||||
void printType(String key, ClassFile cf, String cname, boolean r)
|
||||
throws ConstantPoolException {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, dep(r)));
|
||||
void printType(String key, ClassModel cf, String cname, boolean r) {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.thisClass().asInternalName(), cname, dep(r)));
|
||||
}
|
||||
|
||||
void printMethod(String key, ClassFile cf, String cname, String mname, String rtype,
|
||||
boolean r) throws ConstantPoolException {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, mname, rtype, dep(r)));
|
||||
void printMethod(String key, ClassModel cf, String cname, String mname, String rtype,
|
||||
boolean r) {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.thisClass().asInternalName(), cname, mname, rtype, dep(r)));
|
||||
}
|
||||
|
||||
void printField(String key, ClassFile cf, String cname, String fname,
|
||||
boolean r) throws ConstantPoolException {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, dep(r)));
|
||||
void printField(String key, ClassModel cf, String cname, String fname,
|
||||
boolean r) {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.thisClass().asInternalName(), cname, fname, dep(r)));
|
||||
}
|
||||
|
||||
void printFieldType(String key, ClassFile cf, String cname, String fname, String type,
|
||||
boolean r) throws ConstantPoolException {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, type, dep(r)));
|
||||
void printFieldType(String key, ClassModel cf, String cname, String fname, String type,
|
||||
boolean r) {
|
||||
out.println(Messages.get(key, typeKind(cf), cf.thisClass().asInternalName(), cname, fname, type, dep(r)));
|
||||
}
|
||||
|
||||
void printHasField(ClassFile cf, String fname, String type, boolean r)
|
||||
throws ConstantPoolException {
|
||||
out.println(Messages.get("scan.out.hasfield", typeKind(cf), cf.getName(), fname, type, dep(r)));
|
||||
void printHasField(ClassModel cf, String fname, String type, boolean r)
|
||||
{
|
||||
out.println(Messages.get("scan.out.hasfield", typeKind(cf), cf.thisClass().asInternalName(), fname, type, dep(r)));
|
||||
}
|
||||
|
||||
void printHasMethodParmType(ClassFile cf, String mname, String parmType, boolean r)
|
||||
throws ConstantPoolException {
|
||||
out.println(Messages.get("scan.out.methodparmtype", typeKind(cf), cf.getName(), mname, parmType, dep(r)));
|
||||
void printHasMethodParmType(ClassModel cf, String mname, String parmType, boolean r)
|
||||
{
|
||||
out.println(Messages.get("scan.out.methodparmtype", typeKind(cf), cf.thisClass().asInternalName(), mname, parmType, dep(r)));
|
||||
}
|
||||
|
||||
void printHasMethodRetType(ClassFile cf, String mname, String retType, boolean r)
|
||||
throws ConstantPoolException {
|
||||
out.println(Messages.get("scan.out.methodrettype", typeKind(cf), cf.getName(), mname, retType, dep(r)));
|
||||
void printHasMethodRetType(ClassModel cf, String mname, String retType, boolean r)
|
||||
{
|
||||
out.println(Messages.get("scan.out.methodrettype", typeKind(cf), cf.thisClass().asInternalName(), mname, retType, dep(r)));
|
||||
}
|
||||
|
||||
void printHasOverriddenMethod(ClassFile cf, String overridden, String mname, String desc, boolean r)
|
||||
throws ConstantPoolException {
|
||||
out.println(Messages.get("scan.out.methodoverride", typeKind(cf), cf.getName(), overridden,
|
||||
void printHasOverriddenMethod(ClassModel cf, String overridden, String mname, String desc, boolean r)
|
||||
{
|
||||
out.println(Messages.get("scan.out.methodoverride", typeKind(cf), cf.thisClass().asInternalName(), overridden,
|
||||
mname, desc, dep(r)));
|
||||
}
|
||||
|
||||
@ -253,29 +254,29 @@ public class Scan {
|
||||
* The checkMethod parameter determines whether this checks for a method
|
||||
* or for a field.
|
||||
*
|
||||
* @param targetClass the ClassFile of the class to search
|
||||
* @param targetClass the ClassModel of the class to search
|
||||
* @param targetName the method or field's name
|
||||
* @param targetDesc the methods descriptor (ignored if checkMethod is false)
|
||||
* @param checkMethod true if checking for method, false if checking for field
|
||||
* @return boolean indicating whether the member is present
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
boolean isMemberPresent(ClassFile targetClass,
|
||||
boolean isMemberPresent(ClassModel targetClass,
|
||||
String targetName,
|
||||
String targetDesc,
|
||||
boolean checkMethod)
|
||||
throws ConstantPoolException {
|
||||
{
|
||||
if (checkMethod) {
|
||||
for (Method m : targetClass.methods) {
|
||||
String mname = m.getName(targetClass.constant_pool);
|
||||
String mdesc = targetClass.constant_pool.getUTF8Value(m.descriptor.index);
|
||||
for (var m : targetClass.methods()) {
|
||||
String mname = m.methodName().stringValue();
|
||||
String mdesc = m.methodType().stringValue();
|
||||
if (targetName.equals(mname) && targetDesc.equals(mdesc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Field f : targetClass.fields) {
|
||||
String fname = f.getName(targetClass.constant_pool);
|
||||
for (var f : targetClass.fields()) {
|
||||
String fname = f.fieldName().stringValue();
|
||||
if (targetName.equals(fname)) {
|
||||
return true;
|
||||
}
|
||||
@ -288,14 +289,12 @@ public class Scan {
|
||||
* Adds all interfaces from this class to the deque of interfaces.
|
||||
*
|
||||
* @param intfs the deque of interfaces
|
||||
* @param cf the ClassFile of this class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @param cf the ClassModel of this class
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void addInterfaces(Deque<String> intfs, ClassFile cf)
|
||||
throws ConstantPoolException {
|
||||
int count = cf.interfaces.length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
intfs.addLast(cf.getInterfaceName(i));
|
||||
void addInterfaces(Deque<String> intfs, ClassModel cf) {
|
||||
for (var itf : cf.interfaces()) {
|
||||
intfs.addLast(itf.asInternalName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,7 +306,7 @@ public class Scan {
|
||||
*
|
||||
* TODO: refine error handling
|
||||
*
|
||||
* @param cf the ClassFile of this class
|
||||
* @param cf the ClassModel of this class
|
||||
* @param startClassName the name of the class at which to start searching
|
||||
* @param findName the member name to search for
|
||||
* @param findDesc the method descriptor to search for (ignored for fields)
|
||||
@ -315,15 +314,15 @@ public class Scan {
|
||||
* @param checkStartClass true if the start class should be searched, false if
|
||||
* it should be skipped
|
||||
* @return the name of the class where the member resolved, or null
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
String resolveMember(
|
||||
ClassFile cf, String startClassName, String findName, String findDesc,
|
||||
ClassModel cf, String startClassName, String findName, String findDesc,
|
||||
boolean resolveMethod, boolean checkStartClass)
|
||||
throws ConstantPoolException {
|
||||
ClassFile startClass;
|
||||
{
|
||||
ClassModel startClass;
|
||||
|
||||
if (cf.getName().equals(startClassName)) {
|
||||
if (cf.thisClass().asInternalName().equals(startClassName)) {
|
||||
startClass = cf;
|
||||
} else {
|
||||
startClass = finder.find(startClassName);
|
||||
@ -336,7 +335,7 @@ public class Scan {
|
||||
// follow super_class until it's 0, meaning we've reached Object
|
||||
// accumulate interfaces of superclasses as we go along
|
||||
|
||||
ClassFile curClass = startClass;
|
||||
ClassModel curClass = startClass;
|
||||
Deque<String> intfs = new ArrayDeque<>();
|
||||
while (true) {
|
||||
if ((checkStartClass || curClass != startClass) &&
|
||||
@ -344,12 +343,13 @@ public class Scan {
|
||||
break;
|
||||
}
|
||||
|
||||
if (curClass.super_class == 0) { // reached Object
|
||||
var superclass = curClass.superclass();
|
||||
if (superclass.isEmpty()) { // reached Object
|
||||
curClass = null;
|
||||
break;
|
||||
}
|
||||
|
||||
String superName = curClass.getSuperclassName();
|
||||
String superName = superclass.get().asInternalName();
|
||||
curClass = finder.find(superName);
|
||||
if (curClass == null) {
|
||||
errorNoClass(superName);
|
||||
@ -391,7 +391,7 @@ public class Scan {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
String foundClassName = curClass.getName();
|
||||
String foundClassName = curClass.thisClass().asInternalName();
|
||||
return foundClassName;
|
||||
}
|
||||
}
|
||||
@ -399,11 +399,15 @@ public class Scan {
|
||||
/**
|
||||
* Checks the superclass of this class.
|
||||
*
|
||||
* @param cf the ClassFile of this class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @param cf the ClassModel of this class
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void checkSuper(ClassFile cf) throws ConstantPoolException {
|
||||
String sname = cf.getSuperclassName();
|
||||
void checkSuper(ClassModel cf) {
|
||||
var superclass = cf.superclass();
|
||||
if (superclass.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String sname = superclass.get().asInternalName();
|
||||
DeprData dd = db.getTypeDeprecated(sname);
|
||||
if (dd != null) {
|
||||
printType("scan.out.extends", cf, sname, dd.isForRemoval());
|
||||
@ -413,13 +417,12 @@ public class Scan {
|
||||
/**
|
||||
* Checks the interfaces of this class.
|
||||
*
|
||||
* @param cf the ClassFile of this class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @param cf the ClassModel of this class
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void checkInterfaces(ClassFile cf) throws ConstantPoolException {
|
||||
int ni = cf.interfaces.length;
|
||||
for (int i = 0; i < ni; i++) {
|
||||
String iname = cf.getInterfaceName(i);
|
||||
void checkInterfaces(ClassModel cf) {
|
||||
for (var itf : cf.interfaces()) {
|
||||
String iname = itf.asInternalName();
|
||||
DeprData dd = db.getTypeDeprecated(iname);
|
||||
if (dd != null) {
|
||||
printType("scan.out.implements", cf, iname, dd.isForRemoval());
|
||||
@ -430,13 +433,13 @@ public class Scan {
|
||||
/**
|
||||
* Checks Class_info entries in the constant pool.
|
||||
*
|
||||
* @param cf the ClassFile of this class
|
||||
* @param cf the ClassModel of this class
|
||||
* @param entries constant pool entries collected from this class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void checkClasses(ClassFile cf, CPEntries entries) throws ConstantPoolException {
|
||||
for (ConstantPool.CONSTANT_Class_info ci : entries.classes) {
|
||||
String name = nameFromRefType(ci.getName());
|
||||
void checkClasses(ClassModel cf, CPEntries entries) {
|
||||
for (var ci : entries.classes) {
|
||||
String name = nameFromRefType(ci.asInternalName());
|
||||
if (name != null) {
|
||||
DeprData dd = db.getTypeDeprecated(name);
|
||||
if (dd != null) {
|
||||
@ -449,18 +452,18 @@ public class Scan {
|
||||
/**
|
||||
* Checks methods referred to from the constant pool.
|
||||
*
|
||||
* @param cf the ClassFile of this class
|
||||
* @param cf the ClassModel of this class
|
||||
* @param clname the class name
|
||||
* @param nti the NameAndType_info from a MethodRef or InterfaceMethodRef entry
|
||||
* @param msgKey message key for localization
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void checkMethodRef(ClassFile cf,
|
||||
void checkMethodRef(ClassModel cf,
|
||||
String clname,
|
||||
CONSTANT_NameAndType_info nti,
|
||||
String msgKey) throws ConstantPoolException {
|
||||
String name = nti.getName();
|
||||
String type = nti.getType();
|
||||
NameAndTypeEntry nti,
|
||||
String msgKey) {
|
||||
String name = nti.name().stringValue();
|
||||
String type = nti.type().stringValue();
|
||||
clname = nameFromRefType(clname);
|
||||
if (clname != null) {
|
||||
clname = resolveMember(cf, clname, name, type, true, true);
|
||||
@ -474,15 +477,15 @@ public class Scan {
|
||||
/**
|
||||
* Checks fields referred to from the constant pool.
|
||||
*
|
||||
* @param cf the ClassFile of this class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @param cf the ClassModel of this class
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void checkFieldRef(ClassFile cf,
|
||||
ConstantPool.CONSTANT_Fieldref_info fri) throws ConstantPoolException {
|
||||
String clname = nameFromRefType(fri.getClassName());
|
||||
CONSTANT_NameAndType_info nti = fri.getNameAndTypeInfo();
|
||||
String name = nti.getName();
|
||||
String type = nti.getType();
|
||||
void checkFieldRef(ClassModel cf,
|
||||
FieldRefEntry fri) {
|
||||
String clname = nameFromRefType(fri.owner().asInternalName());
|
||||
var nti = fri.nameAndType();
|
||||
String name = nti.name().stringValue();
|
||||
String type = nti.type().stringValue();
|
||||
|
||||
if (clname != null) {
|
||||
clname = resolveMember(cf, clname, name, type, false, true);
|
||||
@ -496,16 +499,16 @@ public class Scan {
|
||||
/**
|
||||
* Checks the fields declared in this class.
|
||||
*
|
||||
* @param cf the ClassFile of this class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @param cf the ClassModel of this class
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void checkFields(ClassFile cf) throws ConstantPoolException {
|
||||
for (Field f : cf.fields) {
|
||||
String type = nameFromDescType(cf.constant_pool.getUTF8Value(f.descriptor.index));
|
||||
void checkFields(ClassModel cf) {
|
||||
for (var f : cf.fields()) {
|
||||
String type = nameFromDescType(f.fieldType().stringValue());
|
||||
if (type != null) {
|
||||
DeprData dd = db.getTypeDeprecated(type);
|
||||
if (dd != null) {
|
||||
printHasField(cf, f.getName(cf.constant_pool), type, dd.isForRemoval());
|
||||
printHasField(cf, f.fieldName().stringValue(), type, dd.isForRemoval());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -514,17 +517,18 @@ public class Scan {
|
||||
/**
|
||||
* Checks the methods declared in this class.
|
||||
*
|
||||
* @param cf the ClassFile object of this class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @param cf the ClassModel object of this class
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void checkMethods(ClassFile cf) throws ConstantPoolException {
|
||||
for (Method m : cf.methods) {
|
||||
String mname = m.getName(cf.constant_pool);
|
||||
String desc = cf.constant_pool.getUTF8Value(m.descriptor.index);
|
||||
MethodSig sig = MethodSig.fromDesc(desc);
|
||||
void checkMethods(ClassModel cf) {
|
||||
for (var m : cf.methods()) {
|
||||
String mname = m.methodName().stringValue();
|
||||
var desc = m.methodType().stringValue();
|
||||
MethodTypeDesc sig = m.methodTypeSymbol();
|
||||
DeprData dd;
|
||||
|
||||
for (String parm : sig.getParameters()) {
|
||||
for (var parmDesc : sig.parameterArray()) {
|
||||
var parm = parmDesc.descriptorString();
|
||||
parm = nameFromDescType(parm);
|
||||
if (parm != null) {
|
||||
dd = db.getTypeDeprecated(parm);
|
||||
@ -534,7 +538,7 @@ public class Scan {
|
||||
}
|
||||
}
|
||||
|
||||
String ret = nameFromDescType(sig.getReturnType());
|
||||
String ret = nameFromDescType(sig.returnType().descriptorString());
|
||||
if (ret != null) {
|
||||
dd = db.getTypeDeprecated(ret);
|
||||
if (dd != null) {
|
||||
@ -543,7 +547,7 @@ public class Scan {
|
||||
}
|
||||
|
||||
// check overrides
|
||||
String overridden = resolveMember(cf, cf.getName(), mname, desc, true, false);
|
||||
String overridden = resolveMember(cf, cf.thisClass().asInternalName(), mname, desc, true, false);
|
||||
if (overridden != null) {
|
||||
dd = db.getMethodDeprecated(overridden, mname, desc);
|
||||
if (dd != null) {
|
||||
@ -556,12 +560,12 @@ public class Scan {
|
||||
/**
|
||||
* Processes a single class file.
|
||||
*
|
||||
* @param cf the ClassFile of the class
|
||||
* @throws ConstantPoolException if a constant pool entry cannot be found
|
||||
* @param cf the ClassModel of the class
|
||||
* @ if a constant pool entry cannot be found
|
||||
*/
|
||||
void processClass(ClassFile cf) throws ConstantPoolException {
|
||||
void processClass(ClassModel cf) {
|
||||
if (verbose) {
|
||||
out.println(Messages.get("scan.process.class", cf.getName()));
|
||||
out.println(Messages.get("scan.process.class", cf.thisClass().asInternalName()));
|
||||
}
|
||||
|
||||
CPEntries entries = CPEntries.loadFrom(cf);
|
||||
@ -570,19 +574,19 @@ public class Scan {
|
||||
checkInterfaces(cf);
|
||||
checkClasses(cf, entries);
|
||||
|
||||
for (ConstantPool.CONSTANT_Methodref_info mri : entries.methodRefs) {
|
||||
String clname = mri.getClassName();
|
||||
CONSTANT_NameAndType_info nti = mri.getNameAndTypeInfo();
|
||||
for (var mri : entries.methodRefs) {
|
||||
String clname = mri.owner().asInternalName();
|
||||
var nti = mri.nameAndType();
|
||||
checkMethodRef(cf, clname, nti, "scan.out.usesmethod");
|
||||
}
|
||||
|
||||
for (ConstantPool.CONSTANT_InterfaceMethodref_info imri : entries.intfMethodRefs) {
|
||||
String clname = imri.getClassName();
|
||||
CONSTANT_NameAndType_info nti = imri.getNameAndTypeInfo();
|
||||
for (var imri : entries.intfMethodRefs) {
|
||||
String clname = imri.owner().asInternalName();
|
||||
var nti = imri.nameAndType();
|
||||
checkMethodRef(cf, clname, nti, "scan.out.usesintfmethod");
|
||||
}
|
||||
|
||||
for (ConstantPool.CONSTANT_Fieldref_info fri : entries.fieldRefs) {
|
||||
for (var fri : entries.fieldRefs) {
|
||||
checkFieldRef(cf, fri);
|
||||
}
|
||||
|
||||
@ -607,13 +611,14 @@ public class Scan {
|
||||
if (name.endsWith(".class")
|
||||
&& !name.endsWith("package-info.class")
|
||||
&& !name.endsWith("module-info.class")) {
|
||||
processClass(ClassFile.read(jf.getInputStream(entry)));
|
||||
processClass(ClassFile.of().parse(jf
|
||||
.getInputStream(entry).readAllBytes()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (NoSuchFileException nsfe) {
|
||||
errorNoFile(jarname);
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
} catch (IOException | IllegalArgumentException ex) {
|
||||
errorException(ex);
|
||||
}
|
||||
return false;
|
||||
@ -640,10 +645,10 @@ public class Scan {
|
||||
out.println(Messages.get("scan.head.dir", dirname));
|
||||
|
||||
for (Path p : classes) {
|
||||
processClass(ClassFile.read(p));
|
||||
processClass(ClassFile.of().parse(p));
|
||||
}
|
||||
return true;
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
} catch (IOException | IllegalArgumentException ex) {
|
||||
errorException(ex);
|
||||
return false;
|
||||
}
|
||||
@ -657,7 +662,7 @@ public class Scan {
|
||||
*/
|
||||
public boolean processClassName(String className) {
|
||||
try {
|
||||
ClassFile cf = finder.find(className);
|
||||
ClassModel cf = finder.find(className);
|
||||
if (cf == null) {
|
||||
errorNoClass(className);
|
||||
return false;
|
||||
@ -665,7 +670,7 @@ public class Scan {
|
||||
processClass(cf);
|
||||
return true;
|
||||
}
|
||||
} catch (ConstantPoolException ex) {
|
||||
} catch (IllegalArgumentException ex) {
|
||||
errorException(ex);
|
||||
return false;
|
||||
}
|
||||
@ -680,12 +685,12 @@ public class Scan {
|
||||
public boolean processClassFile(String fileName) {
|
||||
Path path = Paths.get(fileName);
|
||||
try {
|
||||
ClassFile cf = ClassFile.read(path);
|
||||
ClassModel cf = ClassFile.of().parse(path);
|
||||
processClass(cf);
|
||||
return true;
|
||||
} catch (NoSuchFileException nsfe) {
|
||||
errorNoFile(fileName);
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
} catch (IOException | IllegalArgumentException ex) {
|
||||
errorException(ex);
|
||||
}
|
||||
return false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
import com.sun.tools.jdeps.Dependency.Location;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
import com.sun.tools.jdeps.Dependency.Location;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,10 +25,7 @@
|
||||
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
import com.sun.tools.classfile.Dependencies.ClassFileError;
|
||||
import com.sun.tools.jdeps.Dependencies.ClassFileError;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
@ -36,13 +33,14 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
@ -54,7 +52,7 @@ import java.util.stream.Stream;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* ClassFileReader reads ClassFile(s) of a given path that can be
|
||||
* ClassFileReader reads ClassModel(s) of a given path that can be
|
||||
* a .class file, a directory, or a JAR file.
|
||||
*/
|
||||
public class ClassFileReader implements Closeable {
|
||||
@ -117,10 +115,10 @@ public class ClassFileReader implements Closeable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ClassFile matching the given binary name
|
||||
* Returns the ClassModel matching the given binary name
|
||||
* or a fully-qualified class name.
|
||||
*/
|
||||
public ClassFile getClassFile(String name) throws IOException {
|
||||
public ClassModel getClassFile(String name) throws IOException {
|
||||
if (name.indexOf('.') > 0) {
|
||||
int i = name.lastIndexOf('.');
|
||||
String pathname = name.replace('.', File.separatorChar) + ".class";
|
||||
@ -137,31 +135,25 @@ public class ClassFileReader implements Closeable {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Iterable<ClassFile> getClassFiles() throws IOException {
|
||||
public Iterable<ClassModel> getClassFiles() throws IOException {
|
||||
return FileIterator::new;
|
||||
}
|
||||
|
||||
protected ClassFile readClassFile(Path p) throws IOException {
|
||||
InputStream is = null;
|
||||
protected ClassModel readClassFile(Path p) throws IOException {
|
||||
try {
|
||||
is = Files.newInputStream(p);
|
||||
return ClassFile.read(is);
|
||||
} catch (ConstantPoolException e) {
|
||||
return ClassFile.of().parse(p);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileError(e);
|
||||
} finally {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Set<String> scan() {
|
||||
try {
|
||||
ClassFile cf = ClassFile.read(path);
|
||||
String name = cf.access_flags.is(AccessFlags.ACC_MODULE)
|
||||
? "module-info" : cf.getName();
|
||||
ClassModel cf = ClassFile.of().parse(path);
|
||||
String name = cf.isModuleInfo()
|
||||
? "module-info" : cf.thisClass().asInternalName();
|
||||
return Collections.singleton(name);
|
||||
} catch (ConstantPoolException|IOException e) {
|
||||
} catch (IllegalArgumentException|IOException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
}
|
||||
@ -175,7 +167,7 @@ public class ClassFileReader implements Closeable {
|
||||
public void close() throws IOException {
|
||||
}
|
||||
|
||||
class FileIterator implements Iterator<ClassFile> {
|
||||
class FileIterator implements Iterator<ClassModel> {
|
||||
int count;
|
||||
FileIterator() {
|
||||
this.count = 0;
|
||||
@ -184,12 +176,12 @@ public class ClassFileReader implements Closeable {
|
||||
return count == 0 && baseFileName.endsWith(".class");
|
||||
}
|
||||
|
||||
public ClassFile next() {
|
||||
public ClassModel next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
try {
|
||||
ClassFile cf = readClassFile(path);
|
||||
ClassModel cf = readClassFile(path);
|
||||
count++;
|
||||
return cf;
|
||||
} catch (IOException e) {
|
||||
@ -228,7 +220,7 @@ public class ClassFileReader implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
public ClassFile getClassFile(String name) throws IOException {
|
||||
public ClassModel getClassFile(String name) throws IOException {
|
||||
if (name.indexOf('.') > 0) {
|
||||
int i = name.lastIndexOf('.');
|
||||
String pathname = name.replace(".", fsSep) + ".class";
|
||||
@ -249,12 +241,12 @@ public class ClassFileReader implements Closeable {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Iterable<ClassFile> getClassFiles() throws IOException {
|
||||
final Iterator<ClassFile> iter = new DirectoryIterator();
|
||||
public Iterable<ClassModel> getClassFiles() throws IOException {
|
||||
final Iterator<ClassModel> iter = new DirectoryIterator();
|
||||
return () -> iter;
|
||||
}
|
||||
|
||||
class DirectoryIterator implements Iterator<ClassFile> {
|
||||
class DirectoryIterator implements Iterator<ClassModel> {
|
||||
private final List<Path> entries;
|
||||
private int index = 0;
|
||||
DirectoryIterator() throws IOException {
|
||||
@ -271,7 +263,7 @@ public class ClassFileReader implements Closeable {
|
||||
return index != entries.size();
|
||||
}
|
||||
|
||||
public ClassFile next() {
|
||||
public ClassModel next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
@ -332,7 +324,7 @@ public class ClassFileReader implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
public ClassFile getClassFile(String name) throws IOException {
|
||||
public ClassModel getClassFile(String name) throws IOException {
|
||||
if (name.indexOf('.') > 0) {
|
||||
int i = name.lastIndexOf('.');
|
||||
String entryName = name.replace('.', '/') + ".class";
|
||||
@ -353,31 +345,31 @@ public class ClassFileReader implements Closeable {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ClassFile readClassFile(JarFile jarfile, JarEntry e) throws IOException {
|
||||
protected ClassModel readClassFile(JarFile jarfile, JarEntry e) throws IOException {
|
||||
try (InputStream is = jarfile.getInputStream(e)) {
|
||||
ClassFile cf = ClassFile.read(is);
|
||||
ClassModel cf = ClassFile.of().parse(is.readAllBytes());
|
||||
// exclude module-info.class since this jarFile is on classpath
|
||||
if (jarfile.isMultiRelease() && !cf.getName().equals("module-info")) {
|
||||
if (jarfile.isMultiRelease() && !cf.isModuleInfo()) {
|
||||
VersionHelper.add(jarfile, e, cf);
|
||||
}
|
||||
return cf;
|
||||
} catch (ConstantPoolException ex) {
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new ClassFileError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<ClassFile> getClassFiles() throws IOException {
|
||||
final Iterator<ClassFile> iter = new JarFileIterator(this, jarfile);
|
||||
public Iterable<ClassModel> getClassFiles() throws IOException {
|
||||
final Iterator<ClassModel> iter = new JarFileIterator(this, jarfile);
|
||||
return () -> iter;
|
||||
}
|
||||
}
|
||||
|
||||
class JarFileIterator implements Iterator<ClassFile> {
|
||||
class JarFileIterator implements Iterator<ClassModel> {
|
||||
protected final JarFileReader reader;
|
||||
protected Iterator<JarEntry> entries;
|
||||
protected JarFile jf;
|
||||
protected JarEntry nextEntry;
|
||||
protected ClassFile cf;
|
||||
protected ClassModel cf;
|
||||
JarFileIterator(JarFileReader reader) {
|
||||
this(reader, null);
|
||||
}
|
||||
@ -413,11 +405,11 @@ public class ClassFileReader implements Closeable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ClassFile next() {
|
||||
public ClassModel next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
ClassFile classFile = cf;
|
||||
ClassModel classFile = cf;
|
||||
cf = null;
|
||||
nextEntry = nextEntry();
|
||||
return classFile;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,31 +23,20 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.classfile;
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.lang.classfile.*;
|
||||
import java.lang.classfile.constantpool.*;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.reflect.AccessFlag;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sun.tools.classfile.Dependency.Filter;
|
||||
import com.sun.tools.classfile.Dependency.Finder;
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
import com.sun.tools.classfile.Type.ArrayType;
|
||||
import com.sun.tools.classfile.Type.ClassSigType;
|
||||
import com.sun.tools.classfile.Type.ClassType;
|
||||
import com.sun.tools.classfile.Type.MethodType;
|
||||
import com.sun.tools.classfile.Type.SimpleType;
|
||||
import com.sun.tools.classfile.Type.TypeParamType;
|
||||
import com.sun.tools.classfile.Type.WildcardType;
|
||||
|
||||
import static com.sun.tools.classfile.ConstantPool.*;
|
||||
import com.sun.tools.jdeps.Dependency.Filter;
|
||||
import com.sun.tools.jdeps.Dependency.Finder;
|
||||
import com.sun.tools.jdeps.Dependency.Location;
|
||||
|
||||
/**
|
||||
* A framework for determining {@link Dependency dependencies} between class files.
|
||||
@ -107,7 +96,7 @@ public class Dependencies {
|
||||
* @throws Dependencies.ClassFileNotFoundException if the classfile cannot be
|
||||
* found
|
||||
*/
|
||||
public ClassFile getClassFile(String className)
|
||||
public ClassModel getClassFile(String className)
|
||||
throws ClassFileNotFoundException;
|
||||
}
|
||||
|
||||
@ -127,7 +116,7 @@ public class Dependencies {
|
||||
* @return the default finder
|
||||
*/
|
||||
public static Finder getDefaultFinder() {
|
||||
return new APIDependencyFinder(AccessFlags.ACC_PRIVATE);
|
||||
return new APIDependencyFinder(ClassFile.ACC_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,9 +124,9 @@ public class Dependencies {
|
||||
* These include the superclass, superinterfaces, and classes referenced in
|
||||
* the declarations of fields and methods. The fields and methods that
|
||||
* are checked can be limited according to a specified access.
|
||||
* The access parameter must be one of {@link AccessFlags#ACC_PUBLIC ACC_PUBLIC},
|
||||
* {@link AccessFlags#ACC_PRIVATE ACC_PRIVATE},
|
||||
* {@link AccessFlags#ACC_PROTECTED ACC_PROTECTED}, or 0 for
|
||||
* The access parameter must be one of {@link ClassFile#ACC_PUBLIC ACC_PUBLIC},
|
||||
* {@link ClassFile#ACC_PRIVATE ACC_PRIVATE},
|
||||
* {@link ClassFile#ACC_PROTECTED ACC_PROTECTED}, or 0 for
|
||||
* package private access. Members with greater than or equal accessibility
|
||||
* to that specified will be searched for dependencies.
|
||||
* @param access the access of members to be checked
|
||||
@ -291,7 +280,7 @@ public class Dependencies {
|
||||
assert (!doneClasses.contains(className));
|
||||
doneClasses.add(className);
|
||||
|
||||
ClassFile cf = classFinder.getClassFile(className);
|
||||
ClassModel cf = classFinder.getClassFile(className);
|
||||
|
||||
// The following code just applies the filter to the dependencies
|
||||
// followed for the transitive closure.
|
||||
@ -466,28 +455,25 @@ public class Dependencies {
|
||||
* This class identifies class names directly or indirectly in the constant pool.
|
||||
*/
|
||||
static class ClassDependencyFinder extends BasicDependencyFinder {
|
||||
public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
|
||||
public Iterable<? extends Dependency> findDependencies(ClassModel classfile) {
|
||||
Visitor v = new Visitor(classfile);
|
||||
for (CPInfo cpInfo: classfile.constant_pool.entries()) {
|
||||
for (var cpInfo: classfile.constantPool()) {
|
||||
v.scan(cpInfo);
|
||||
}
|
||||
try {
|
||||
v.addClass(classfile.super_class);
|
||||
v.addClasses(classfile.interfaces);
|
||||
v.scan(classfile.attributes);
|
||||
classfile.superclass().ifPresent(v::addClass);
|
||||
v.addClasses(classfile.interfaces());
|
||||
v.scanAttributes(classfile);
|
||||
|
||||
for (Field f : classfile.fields) {
|
||||
v.scan(f.descriptor, f.attributes);
|
||||
for (var f : classfile.fields()) {
|
||||
v.scan(f.fieldTypeSymbol());
|
||||
v.scanAttributes(f);
|
||||
}
|
||||
for (Method m : classfile.methods) {
|
||||
v.scan(m.descriptor, m.attributes);
|
||||
Exceptions_attribute e =
|
||||
(Exceptions_attribute)m.attributes.get(Attribute.Exceptions);
|
||||
if (e != null) {
|
||||
v.addClasses(e.exception_index_table);
|
||||
}
|
||||
for (var m : classfile.methods()) {
|
||||
v.scan(m.methodTypeSymbol());
|
||||
v.scanAttributes(m);
|
||||
}
|
||||
} catch (ConstantPoolException e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
|
||||
@ -502,9 +488,9 @@ public class Dependencies {
|
||||
static class APIDependencyFinder extends BasicDependencyFinder {
|
||||
APIDependencyFinder(int access) {
|
||||
switch (access) {
|
||||
case AccessFlags.ACC_PUBLIC:
|
||||
case AccessFlags.ACC_PROTECTED:
|
||||
case AccessFlags.ACC_PRIVATE:
|
||||
case ClassFile.ACC_PUBLIC:
|
||||
case ClassFile.ACC_PROTECTED:
|
||||
case ClassFile.ACC_PRIVATE:
|
||||
case 0:
|
||||
showAccess = access;
|
||||
break;
|
||||
@ -514,41 +500,40 @@ public class Dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
|
||||
public Iterable<? extends Dependency> findDependencies(ClassModel classfile) {
|
||||
try {
|
||||
Visitor v = new Visitor(classfile);
|
||||
v.addClass(classfile.super_class);
|
||||
v.addClasses(classfile.interfaces);
|
||||
classfile.superclass().ifPresent(v::addClass);
|
||||
v.addClasses(classfile.interfaces());
|
||||
// inner classes?
|
||||
for (Field f : classfile.fields) {
|
||||
if (checkAccess(f.access_flags))
|
||||
v.scan(f.descriptor, f.attributes);
|
||||
for (var f : classfile.fields()) {
|
||||
if (checkAccess(f.flags())) {
|
||||
v.scan(f.fieldTypeSymbol());
|
||||
v.scanAttributes(f);
|
||||
}
|
||||
}
|
||||
for (Method m : classfile.methods) {
|
||||
if (checkAccess(m.access_flags)) {
|
||||
v.scan(m.descriptor, m.attributes);
|
||||
Exceptions_attribute e =
|
||||
(Exceptions_attribute) m.attributes.get(Attribute.Exceptions);
|
||||
if (e != null)
|
||||
v.addClasses(e.exception_index_table);
|
||||
for (var m : classfile.methods()) {
|
||||
if (checkAccess(m.flags())) {
|
||||
v.scan(m.methodTypeSymbol());
|
||||
v.scanAttributes(m);
|
||||
}
|
||||
}
|
||||
return v.deps;
|
||||
} catch (ConstantPoolException e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean checkAccess(AccessFlags flags) {
|
||||
// code copied from javap.Options.checkAccess
|
||||
boolean isPublic = flags.is(AccessFlags.ACC_PUBLIC);
|
||||
boolean isProtected = flags.is(AccessFlags.ACC_PROTECTED);
|
||||
boolean isPrivate = flags.is(AccessFlags.ACC_PRIVATE);
|
||||
boolean isPublic = flags.has(AccessFlag.PUBLIC);
|
||||
boolean isProtected = flags.has(AccessFlag.PROTECTED);
|
||||
boolean isPrivate = flags.has(AccessFlag.PRIVATE);
|
||||
boolean isPackage = !(isPublic || isProtected || isPrivate);
|
||||
|
||||
if ((showAccess == AccessFlags.ACC_PUBLIC) && (isProtected || isPrivate || isPackage))
|
||||
if ((showAccess == ClassFile.ACC_PUBLIC) && (isProtected || isPrivate || isPackage))
|
||||
return false;
|
||||
else if ((showAccess == AccessFlags.ACC_PROTECTED) && (isPrivate || isPackage))
|
||||
else if ((showAccess == ClassFile.ACC_PROTECTED) && (isPrivate || isPackage))
|
||||
return false;
|
||||
else if ((showAccess == 0) && (isPrivate))
|
||||
return false;
|
||||
@ -566,238 +551,158 @@ public class Dependencies {
|
||||
return locations.computeIfAbsent(className, SimpleLocation::new);
|
||||
}
|
||||
|
||||
class Visitor implements ConstantPool.Visitor<Void,Void>, Type.Visitor<Void, Void> {
|
||||
private ConstantPool constant_pool;
|
||||
private Location origin;
|
||||
Set<Dependency> deps;
|
||||
class Visitor {
|
||||
private final Location origin;
|
||||
final Set<Dependency> deps;
|
||||
|
||||
Visitor(ClassFile classFile) {
|
||||
Visitor(ClassModel classFile) {
|
||||
try {
|
||||
constant_pool = classFile.constant_pool;
|
||||
origin = getLocation(classFile.getName());
|
||||
deps = new HashSet<>();
|
||||
} catch (ConstantPoolException e) {
|
||||
origin = getLocation(classFile.thisClass().asInternalName());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
deps = new HashSet<>();
|
||||
}
|
||||
|
||||
void scan(Descriptor d, Attributes attrs) {
|
||||
try {
|
||||
scan(new Signature(d.index).getType(constant_pool));
|
||||
scan(attrs);
|
||||
} catch (ConstantPoolException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
private void addDependency(String internalName) {
|
||||
deps.add(new SimpleDependency(origin, getLocation(internalName)));
|
||||
}
|
||||
|
||||
void scan(CPInfo cpInfo) {
|
||||
cpInfo.accept(this, null);
|
||||
private void addClass(ClassEntry ce) throws IllegalArgumentException {
|
||||
assert ce.name().charAt(0) != '[';
|
||||
addDependency(ce.asInternalName());
|
||||
}
|
||||
|
||||
void scan(Type t) {
|
||||
t.accept(this, null);
|
||||
}
|
||||
|
||||
void scan(Attributes attrs) {
|
||||
try {
|
||||
Signature_attribute sa = (Signature_attribute)attrs.get(Attribute.Signature);
|
||||
if (sa != null)
|
||||
scan(sa.getParsedSignature().getType(constant_pool));
|
||||
|
||||
scan((RuntimeVisibleAnnotations_attribute)
|
||||
attrs.get(Attribute.RuntimeVisibleAnnotations));
|
||||
scan((RuntimeVisibleParameterAnnotations_attribute)
|
||||
attrs.get(Attribute.RuntimeVisibleParameterAnnotations));
|
||||
} catch (ConstantPoolException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void scan(RuntimeAnnotations_attribute attr) throws ConstantPoolException {
|
||||
if (attr == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < attr.annotations.length; i++) {
|
||||
int index = attr.annotations[i].type_index;
|
||||
scan(new Signature(index).getType(constant_pool));
|
||||
}
|
||||
}
|
||||
|
||||
private void scan(RuntimeParameterAnnotations_attribute attr) throws ConstantPoolException {
|
||||
if (attr == null) {
|
||||
return;
|
||||
}
|
||||
for (int param = 0; param < attr.parameter_annotations.length; param++) {
|
||||
for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
|
||||
int index = attr.parameter_annotations[param][i].type_index;
|
||||
scan(new Signature(index).getType(constant_pool));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addClass(int index) throws ConstantPoolException {
|
||||
if (index != 0) {
|
||||
String name = constant_pool.getClassInfo(index).getBaseName();
|
||||
if (name != null)
|
||||
addDependency(name);
|
||||
}
|
||||
}
|
||||
|
||||
void addClasses(int[] indices) throws ConstantPoolException {
|
||||
for (int i: indices)
|
||||
private void addClasses(Collection<? extends ClassEntry> ces) throws IllegalArgumentException {
|
||||
for (var i: ces)
|
||||
addClass(i);
|
||||
}
|
||||
|
||||
private void addDependency(String name) {
|
||||
deps.add(new SimpleDependency(origin, getLocation(name)));
|
||||
private void scan(ClassDesc cd) {
|
||||
while (cd.isArray()) {
|
||||
cd = cd.componentType();
|
||||
}
|
||||
if (cd.isClassOrInterface()) {
|
||||
var desc = cd.descriptorString();
|
||||
addDependency(desc.substring(1, desc.length() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// ConstantPool.Visitor methods
|
||||
private void scan(MethodTypeDesc mtd) {
|
||||
scan(mtd.returnType());
|
||||
for (int i = 0; i < mtd.parameterCount(); i++) {
|
||||
scan(mtd.parameterType(i));
|
||||
}
|
||||
}
|
||||
|
||||
public Void visitClass(CONSTANT_Class_info info, Void p) {
|
||||
void scanAttributes(AttributedElement attrs) {
|
||||
try {
|
||||
if (info.getName().startsWith("["))
|
||||
new Signature(info.name_index).getType(constant_pool).accept(this, null);
|
||||
else
|
||||
addDependency(info.getBaseName());
|
||||
return null;
|
||||
} catch (ConstantPoolException e) {
|
||||
var sa = attrs.findAttribute(Attributes.SIGNATURE).orElse(null);
|
||||
if (sa != null) {
|
||||
switch (attrs) {
|
||||
case ClassModel _ -> scan(sa.asClassSignature());
|
||||
case MethodModel _ -> scan(sa.asMethodSignature());
|
||||
default -> scan(sa.asTypeSignature());
|
||||
}
|
||||
}
|
||||
|
||||
var rvaa = attrs.findAttribute(Attributes.RUNTIME_VISIBLE_ANNOTATIONS).orElse(null);
|
||||
if (rvaa != null) {
|
||||
for (var anno : rvaa.annotations()) {
|
||||
scan(anno.classSymbol());
|
||||
}
|
||||
}
|
||||
|
||||
var rvpaa = attrs.findAttribute(Attributes.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS).orElse(null);
|
||||
if (rvpaa != null) {
|
||||
for (var parameter : rvpaa.parameterAnnotations()) {
|
||||
for (var anno : parameter) {
|
||||
scan(anno.classSymbol());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var exceptions = attrs.findAttribute(Attributes.EXCEPTIONS).orElse(null);
|
||||
if (exceptions != null) {
|
||||
for (var e : exceptions.exceptions()) {
|
||||
addClass(e);
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Void visitDouble(CONSTANT_Double_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
// ConstantPool scanning
|
||||
|
||||
public Void visitFieldref(CONSTANT_Fieldref_info info, Void p) {
|
||||
return visitRef(info, p);
|
||||
}
|
||||
|
||||
public Void visitFloat(CONSTANT_Float_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitInteger(CONSTANT_Integer_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
|
||||
return visitRef(info, p);
|
||||
}
|
||||
|
||||
public Void visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitDynamicConstant(CONSTANT_Dynamic_info info, Void aVoid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitLong(CONSTANT_Long_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitMethodType(CONSTANT_MethodType_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitMethodref(CONSTANT_Methodref_info info, Void p) {
|
||||
return visitRef(info, p);
|
||||
}
|
||||
|
||||
public Void visitModule(CONSTANT_Module_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
|
||||
void scan(PoolEntry cpInfo) {
|
||||
try {
|
||||
new Signature(info.type_index).getType(constant_pool).accept(this, null);
|
||||
return null;
|
||||
} catch (ConstantPoolException e) {
|
||||
switch (cpInfo) {
|
||||
case ClassEntry clazz -> scan(clazz.asSymbol());
|
||||
case FieldRefEntry field -> scan(field.owner().asSymbol());
|
||||
case MethodRefEntry method -> scan(method.owner().asSymbol());
|
||||
case InterfaceMethodRefEntry interfaceMethod -> scan(interfaceMethod.owner().asSymbol());
|
||||
case NameAndTypeEntry nat -> {
|
||||
var desc = nat.type();
|
||||
if (desc.charAt(0) == '(') {
|
||||
scan(MethodTypeDesc.ofDescriptor(desc.stringValue()));
|
||||
} else {
|
||||
scan(ClassDesc.ofDescriptor(desc.stringValue()));
|
||||
}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Void visitPackage(CONSTANT_Package_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
// Signature scanning
|
||||
|
||||
public Void visitString(CONSTANT_String_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitUtf8(CONSTANT_Utf8_info info, Void p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Void visitRef(CPRefInfo info, Void p) {
|
||||
try {
|
||||
visitClass(info.getClassInfo(), p);
|
||||
return null;
|
||||
} catch (ConstantPoolException e) {
|
||||
throw new ClassFileError(e);
|
||||
private void scan(MethodSignature sig) {
|
||||
for (var param : sig.typeParameters()) {
|
||||
scan(param);
|
||||
}
|
||||
for (var param : sig.arguments()) {
|
||||
scan(param);
|
||||
}
|
||||
scan(sig.result());
|
||||
for (var thrown : sig.throwableSignatures()) {
|
||||
scan(thrown);
|
||||
}
|
||||
}
|
||||
|
||||
// Type.Visitor methods
|
||||
|
||||
private void findDependencies(Type t) {
|
||||
if (t != null)
|
||||
t.accept(this, null);
|
||||
}
|
||||
|
||||
private void findDependencies(List<? extends Type> ts) {
|
||||
if (ts != null) {
|
||||
for (Type t: ts)
|
||||
t.accept(this, null);
|
||||
private void scan(ClassSignature sig) {
|
||||
for (var param : sig.typeParameters()) {
|
||||
scan(param);
|
||||
}
|
||||
scan(sig.superclassSignature());
|
||||
for (var itf : sig.superinterfaceSignatures()) {
|
||||
scan(itf);
|
||||
}
|
||||
}
|
||||
|
||||
public Void visitSimpleType(SimpleType type, Void p) {
|
||||
return null;
|
||||
private void scan(Signature.TypeParam param) {
|
||||
param.classBound().ifPresent(this::scan);
|
||||
for (var itf : param.interfaceBounds()) {
|
||||
scan(itf);
|
||||
}
|
||||
}
|
||||
|
||||
public Void visitArrayType(ArrayType type, Void p) {
|
||||
findDependencies(type.elemType);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitMethodType(MethodType type, Void p) {
|
||||
findDependencies(type.paramTypes);
|
||||
findDependencies(type.returnType);
|
||||
findDependencies(type.throwsTypes);
|
||||
findDependencies(type.typeParamTypes);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitClassSigType(ClassSigType type, Void p) {
|
||||
findDependencies(type.superclassType);
|
||||
findDependencies(type.superinterfaceTypes);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitClassType(ClassType type, Void p) {
|
||||
findDependencies(type.outerType);
|
||||
addDependency(type.getBinaryName());
|
||||
findDependencies(type.typeArgs);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitTypeParamType(TypeParamType type, Void p) {
|
||||
findDependencies(type.classBound);
|
||||
findDependencies(type.interfaceBounds);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitWildcardType(WildcardType type, Void p) {
|
||||
findDependencies(type.boundType);
|
||||
return null;
|
||||
private void scan(Signature sig) {
|
||||
switch (sig) {
|
||||
case Signature.ClassTypeSig ct -> {
|
||||
ct.outerType().ifPresent(this::scan);
|
||||
scan(ct.classDesc());
|
||||
for (var arg : ct.typeArgs()) {
|
||||
if (arg instanceof Signature.TypeArg.Bounded bounded) {
|
||||
scan(bounded.boundType());
|
||||
}
|
||||
}
|
||||
}
|
||||
case Signature.ArrayTypeSig at -> scan(at.componentSignature());
|
||||
case Signature.BaseTypeSig _, Signature.TypeVarSig _ -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,9 +23,11 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.classfile;
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
|
||||
import java.lang.classfile.ClassModel;
|
||||
|
||||
/**
|
||||
* A directed relationship between two {@link Dependency.Location Location}s.
|
||||
* Subtypes of {@code Dependency} may provide additional detail about the dependency.
|
||||
@ -56,7 +58,7 @@ public interface Dependency {
|
||||
* @param classfile the class file to be examined
|
||||
* @return the dependencies located in the given class file.
|
||||
*/
|
||||
public Iterable<? extends Dependency> findDependencies(ClassFile classfile);
|
||||
public Iterable<? extends Dependency> findDependencies(ClassModel classfile);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,17 +28,15 @@ import static com.sun.tools.jdeps.Module.*;
|
||||
import static com.sun.tools.jdeps.Analyzer.NOT_FOUND;
|
||||
import static java.util.stream.Collectors.*;
|
||||
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
import com.sun.tools.classfile.Dependencies;
|
||||
import com.sun.tools.classfile.Dependencies.ClassFileError;
|
||||
import com.sun.tools.classfile.Dependency;
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
import com.sun.tools.jdeps.Dependencies.ClassFileError;
|
||||
import com.sun.tools.jdeps.Dependency.Location;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.lang.classfile.AccessFlags;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.lang.reflect.AccessFlag;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
@ -46,7 +44,6 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -176,20 +173,20 @@ class DependencyFinder {
|
||||
trace("parsing %s %s%n", archive.getName(), archive.getPathName());
|
||||
FutureTask<Set<Location>> task = new FutureTask<>(() -> {
|
||||
Set<Location> targets = new HashSet<>();
|
||||
for (ClassFile cf : archive.reader().getClassFiles()) {
|
||||
if (cf.access_flags.is(AccessFlags.ACC_MODULE))
|
||||
for (var cf : archive.reader().getClassFiles()) {
|
||||
if (cf.isModuleInfo())
|
||||
continue;
|
||||
|
||||
String classFileName;
|
||||
try {
|
||||
classFileName = cf.getName();
|
||||
} catch (ConstantPoolException e) {
|
||||
classFileName = cf.thisClass().asInternalName();
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileError(e);
|
||||
}
|
||||
|
||||
// filter source class/archive
|
||||
String cn = classFileName.replace('/', '.');
|
||||
if (!finder.accept(archive, cn, cf.access_flags))
|
||||
if (!finder.accept(archive, cn, cf.flags()))
|
||||
continue;
|
||||
|
||||
// tests if this class matches the -include
|
||||
@ -217,24 +214,24 @@ class DependencyFinder {
|
||||
private Set<Location> parse(Archive archive, Finder finder, String name)
|
||||
throws IOException
|
||||
{
|
||||
ClassFile cf = archive.reader().getClassFile(name);
|
||||
var cf = archive.reader().getClassFile(name);
|
||||
if (cf == null) {
|
||||
throw new IllegalArgumentException(archive.getName() +
|
||||
" does not contain " + name);
|
||||
}
|
||||
|
||||
if (cf.access_flags.is(AccessFlags.ACC_MODULE))
|
||||
if (cf.isModuleInfo())
|
||||
return Collections.emptySet();
|
||||
|
||||
Set<Location> targets = new HashSet<>();
|
||||
String cn;
|
||||
try {
|
||||
cn = cf.getName().replace('/', '.');
|
||||
} catch (ConstantPoolException e) {
|
||||
cn = cf.thisClass().asInternalName().replace('/', '.');
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new Dependencies.ClassFileError(e);
|
||||
}
|
||||
|
||||
if (!finder.accept(archive, cn, cf.access_flags))
|
||||
if (!finder.accept(archive, cn, cf.flags()))
|
||||
return targets;
|
||||
|
||||
// tests if this class matches the -include
|
||||
@ -296,7 +293,7 @@ class DependencyFinder {
|
||||
Finder(boolean apiOnly) {
|
||||
this.apiOnly = apiOnly;
|
||||
this.finder = apiOnly
|
||||
? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
|
||||
? Dependencies.getAPIFinder(ClassFile.ACC_PROTECTED)
|
||||
: Dependencies.getClassDependencyFinder();
|
||||
|
||||
}
|
||||
@ -309,12 +306,12 @@ class DependencyFinder {
|
||||
// if -apionly is specified, analyze only exported and public types
|
||||
// All packages are exported in unnamed module.
|
||||
return apiOnly ? archive.getModule().isExported(pn) &&
|
||||
accessFlags.is(AccessFlags.ACC_PUBLIC)
|
||||
accessFlags.has(AccessFlag.PUBLIC)
|
||||
: true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
|
||||
public Iterable<? extends Dependency> findDependencies(ClassModel classfile) {
|
||||
return finder.findDependencies(classfile);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,10 +25,9 @@
|
||||
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
import com.sun.tools.jdeps.Dependency.Location;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,8 +28,6 @@ package com.sun.tools.jdeps;
|
||||
import static com.sun.tools.jdeps.Module.trace;
|
||||
import static java.util.stream.Collectors.*;
|
||||
|
||||
import com.sun.tools.classfile.Dependency;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,9 +24,7 @@
|
||||
*/
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import com.sun.tools.classfile.Dependencies;
|
||||
import com.sun.tools.classfile.Dependency;
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
import com.sun.tools.jdeps.Dependency.Location;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,8 +29,6 @@ import static com.sun.tools.jdeps.Module.*;
|
||||
import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
|
||||
import static java.util.stream.Collectors.*;
|
||||
|
||||
import com.sun.tools.classfile.Dependency;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,9 +25,7 @@
|
||||
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.jar.JarEntry;
|
||||
@ -44,8 +42,8 @@ public class VersionHelper {
|
||||
return classname;
|
||||
}
|
||||
|
||||
public static void add(JarFile jarfile, JarEntry e, ClassFile cf)
|
||||
throws ConstantPoolException
|
||||
public static void add(JarFile jarfile, JarEntry e, ClassModel cf)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
String realName = e.getRealName();
|
||||
if (realName.startsWith(META_INF_VERSIONS)) {
|
||||
@ -54,7 +52,7 @@ public class VersionHelper {
|
||||
if (n > 0) {
|
||||
String version = realName.substring(len, n);
|
||||
assert (Integer.parseInt(version) > 8);
|
||||
String name = cf.getName().replace('/', '.');
|
||||
String name = cf.thisClass().asInternalName().replace('/', '.');
|
||||
String v = nameToVersion.computeIfAbsent(name, _n -> version);
|
||||
if (!version.equals(v)) {
|
||||
throw new MultiReleaseException("err.multirelease.version.associated",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,13 +22,16 @@
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.tools.*;
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
import com.sun.tools.classfile.Dependencies.*;
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
import com.sun.tools.jdeps.Dependencies;
|
||||
import com.sun.tools.jdeps.Dependencies.*;
|
||||
import com.sun.tools.jdeps.Dependency;
|
||||
import com.sun.tools.jdeps.Dependency.Location;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
@ -140,7 +143,7 @@ public class GetDeps {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassFile getClassFile(String className) throws ClassFileNotFoundException {
|
||||
public ClassModel getClassFile(String className) throws ClassFileNotFoundException {
|
||||
try {
|
||||
JavaFileObject fo = fm.getJavaFileForInput(
|
||||
StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
|
||||
@ -151,11 +154,11 @@ public class GetDeps {
|
||||
throw new ClassFileNotFoundException(className);
|
||||
InputStream in = fo.openInputStream();
|
||||
try {
|
||||
return ClassFile.read(in);
|
||||
return ClassFile.of().parse(in.readAllBytes());
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
} catch (ConstantPoolException e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ClassFileNotFoundException(className, e);
|
||||
} catch (IOException e) {
|
||||
throw new ClassFileNotFoundException(className, e);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,9 +24,10 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 6907575
|
||||
* @modules jdk.jdeps/com.sun.tools.classfile
|
||||
* @modules jdk.jdeps/com.sun.tools.jdeps
|
||||
* jdk.compiler/com.sun.tools.javac.file
|
||||
* jdk.compiler/com.sun.tools.javac.util
|
||||
* @enablePreview
|
||||
* @build GetDeps p.C1
|
||||
* @run main T6907575
|
||||
*/
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Simple tests for method signature parsing
|
||||
* @modules jdk.jdeps/com.sun.tools.jdeprscan.scan
|
||||
* @build TestMethodSig
|
||||
* @run testng jdk.jdeprscan.TestMethodSig
|
||||
*/
|
||||
|
||||
package jdk.jdeprscan;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static com.sun.tools.jdeprscan.scan.MethodSig.fromDesc;
|
||||
|
||||
public class TestMethodSig {
|
||||
@Test
|
||||
public void testSimple() {
|
||||
assertEquals(fromDesc("(Ljava/rmi/RMISecurityManager;)Ljava/lang/Object;").toString(),
|
||||
"parameters 0=Ljava/rmi/RMISecurityManager; return Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultParamVoidReturn() {
|
||||
assertEquals(fromDesc("([[IZLjava/lang/String;B[J)V").toString(),
|
||||
"parameters 0=[[I 1=Z 2=Ljava/lang/String; 3=B 4=[J return V");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoParams() {
|
||||
assertEquals(fromDesc("()J").toString(),
|
||||
"parameters none return J");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMissingReturnType() {
|
||||
fromDesc("(ISJZ)");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user