8332109: Convert remaining tests using com.sun.tools.classfile to ClassFile API

Reviewed-by: asotona
This commit is contained in:
Chen Liang 2024-05-17 12:24:39 +00:00 committed by Adam Sotona
parent e0d1c4b38c
commit beeffd4671
19 changed files with 442 additions and 1316 deletions

View File

@ -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,22 +25,18 @@
* @test
* @bug 8140450
* @summary Basic test for the StackWalker::getByteCodeIndex method
* @modules jdk.jdeps/com.sun.tools.classfile
* @enablePreview
* @run main TestBCI
*/
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Descriptor;
import com.sun.tools.classfile.LineNumberTable_attribute;
import com.sun.tools.classfile.Method;
import java.lang.StackWalker.StackFrame;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;
import java.lang.constant.MethodTypeDesc;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
@ -66,12 +62,12 @@ public class TestBCI {
private final Map<String, MethodInfo> methods;
private final Class<?> clazz;
TestBCI(Class<?> c) throws ConstantPoolException, IOException {
TestBCI(Class<?> c) throws IllegalArgumentException, IOException {
Map<String, MethodInfo> methods;
String filename = c.getName().replace('.', '/') + ".class";
try (InputStream in = c.getResourceAsStream(filename)) {
ClassFile cf = ClassFile.read(in);
methods = Arrays.stream(cf.methods)
var cf = ClassFile.of().parse(in.readAllBytes());
methods = cf.methods().stream()
.map(m -> new MethodInfo(cf, m))
.collect(Collectors.toMap(MethodInfo::name, Function.identity()));
}
@ -129,37 +125,20 @@ public class TestBCI {
}
static class MethodInfo {
final Method method;
final MethodModel method;
final String name;
final String paramTypes;
final String returnType;
final MethodTypeDesc desc;
final Map<Integer, SortedSet<Integer>> bciToLineNumbers = new HashMap<>();
MethodInfo(ClassFile cf, Method m) {
MethodInfo(ClassModel cf, MethodModel m) {
this.method = m;
String name;
String paramTypes;
String returnType;
LineNumberTable_attribute.Entry[] lineNumberTable;
try {
// method name
name = m.getName(cf.constant_pool);
// signature
paramTypes = m.descriptor.getParameterTypes(cf.constant_pool);
returnType = m.descriptor.getReturnType(cf.constant_pool);
Code_attribute codeAttr = (Code_attribute)
m.attributes.get(Attribute.Code);
lineNumberTable = ((LineNumberTable_attribute)
codeAttr.attributes.get(Attribute.LineNumberTable)).line_number_table;
} catch (ConstantPoolException|Descriptor.InvalidDescriptor e) {
throw new RuntimeException(e);
}
this.name = name;
this.paramTypes = paramTypes;
this.returnType = returnType;
Arrays.stream(lineNumberTable).forEach(entry ->
bciToLineNumbers.computeIfAbsent(entry.start_pc, _n -> new TreeSet<>())
.add(entry.line_number));
this.name = m.methodName().stringValue();
this.desc = m.methodTypeSymbol();
m.code().orElseThrow(() -> new IllegalArgumentException("Missing Code in " + m))
.findAttribute(Attributes.LINE_NUMBER_TABLE)
.orElseThrow(() -> new IllegalArgumentException("Missing LineNumberTable in " + m))
.lineNumbers().forEach(entry ->
bciToLineNumbers.computeIfAbsent(entry.startPc(), _ -> new TreeSet<>())
.add(entry.lineNumber()));
}
String name() {
@ -178,7 +157,7 @@ public class TestBCI {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(name);
sb.append(paramTypes).append(returnType).append(" ");
sb.append(desc.displayDescriptor()).append(" ");
bciToLineNumbers.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> sb.append("bci:").append(entry.getKey()).append(" ")

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, 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
@ -21,12 +21,16 @@
* questions.
*/
import com.sun.tools.classfile.*;
import static com.sun.tools.classfile.ConstantPool.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;
import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.MethodRefEntry;
import java.lang.classfile.instruction.InvokeInstruction;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.Files;
@ -47,7 +51,7 @@ import java.util.stream.Stream;
* @bug 8010117
* @summary Verify if CallerSensitive methods are annotated with
* CallerSensitive annotation
* @modules jdk.jdeps/com.sun.tools.classfile jdk.jdeps/com.sun.tools.jdeps
* @enablePreview
* @build CallerSensitiveFinder
* @run main/othervm/timeout=900 CallerSensitiveFinder
*/
@ -87,58 +91,71 @@ public class CallerSensitiveFinder {
}
private final List<String> csMethodsMissingAnnotation = new CopyOnWriteArrayList<>();
private final ReferenceFinder finder;
public CallerSensitiveFinder() {
this.finder = new ReferenceFinder(getFilter(), getVisitor());
pool = Executors.newFixedThreadPool(numThreads);
}
private ReferenceFinder.Filter getFilter() {
final String classname = "jdk/internal/reflect/Reflection";
final String method = "getCallerClass";
return new ReferenceFinder.Filter() {
public boolean accept(ConstantPool cpool, CPRefInfo cpref) {
try {
CONSTANT_NameAndType_info nat = cpref.getNameAndTypeInfo();
return cpref.getClassName().equals(classname) && nat.getName().equals(method);
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
private void check(ClassModel clazz) {
final String className = "jdk/internal/reflect/Reflection";
final String methodName = "getCallerClass";
boolean checkMethods = false;
for (var pe : clazz.constantPool()) {
if (pe instanceof MethodRefEntry ref
&& ref.owner().name().equalsString(className)
&& ref.name().equalsString(methodName)) {
checkMethods = true;
}
}
if (!checkMethods)
return;
for (var method : clazz.methods()) {
var code = method.code().orElse(null);
if (code == null)
continue;
boolean needsCsm = false;
for (var element : code) {
if (element instanceof InvokeInstruction invoke
&& invoke.opcode() == Opcode.INVOKESTATIC
&& invoke.method() instanceof MethodRefEntry ref
&& ref.owner().name().equalsString(className)
&& ref.name().equalsString(methodName)) {
needsCsm = true;
break;
}
}
};
if (needsCsm) {
process(clazz, method);
}
}
}
private ReferenceFinder.Visitor getVisitor() {
return new ReferenceFinder.Visitor() {
public void visit(ClassFile cf, Method m, List<CPRefInfo> refs) {
try {
// ignore jdk.unsupported/sun.reflect.Reflection.getCallerClass
// which is a "special" delegate to the internal getCallerClass
if (cf.getName().equals("sun/reflect/Reflection") &&
m.getName(cf.constant_pool).equals("getCallerClass"))
return;
private void process(ClassModel cf, MethodModel m) {
// ignore jdk.unsupported/sun.reflect.Reflection.getCallerClass
// which is a "special" delegate to the internal getCallerClass
if (cf.thisClass().name().equalsString("sun/reflect/Reflection") &&
m.methodName().equalsString("getCallerClass"))
return;
String name = String.format("%s#%s %s", cf.getName(),
m.getName(cf.constant_pool),
m.descriptor.getValue(cf.constant_pool));
if (!CallerSensitiveFinder.isCallerSensitive(m, cf.constant_pool)) {
csMethodsMissingAnnotation.add(name);
System.err.println("Missing @CallerSensitive: " + name);
} else {
if (verbose) {
System.out.format("@CS %s%n", name);
}
}
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
}
String name = cf.thisClass().asInternalName() + '#'
+ m.methodName().stringValue() + ' '
+ m.methodType().stringValue();
if (!CallerSensitiveFinder.isCallerSensitive(m)) {
csMethodsMissingAnnotation.add(name);
System.err.println("Missing @CallerSensitive: " + name);
} else {
if (verbose) {
System.out.format("@CS %s%n", name);
}
};
}
}
public List<String> run(Stream<Path> classes)throws IOException, InterruptedException,
ExecutionException, ConstantPoolException
ExecutionException, IllegalArgumentException
{
classes.forEach(p -> pool.submit(getTask(p)));
waitForCompletion();
@ -146,16 +163,11 @@ public class CallerSensitiveFinder {
}
private static final String CALLER_SENSITIVE_ANNOTATION = "Ljdk/internal/reflect/CallerSensitive;";
private static boolean isCallerSensitive(Method m, ConstantPool cp)
throws ConstantPoolException
{
RuntimeAnnotations_attribute attr =
(RuntimeAnnotations_attribute)m.attributes.get(Attribute.RuntimeVisibleAnnotations);
private static boolean isCallerSensitive(MethodModel m) {
var attr = m.findAttribute(Attributes.RUNTIME_VISIBLE_ANNOTATIONS).orElse(null);
if (attr != null) {
for (int i = 0; i < attr.annotations.length; i++) {
Annotation ann = attr.annotations[i];
String annType = cp.getUTF8Value(ann.type_index);
if (CALLER_SENSITIVE_ANNOTATION.equals(annType)) {
for (var ann : attr.annotations()) {
if (ann.className().equalsString(CALLER_SENSITIVE_ANNOTATION)) {
return true;
}
}
@ -174,12 +186,11 @@ public class CallerSensitiveFinder {
private FutureTask<Void> getTask(Path p) {
FutureTask<Void> task = new FutureTask<>(new Callable<>() {
public Void call() throws Exception {
try (InputStream is = Files.newInputStream(p)) {
finder.parse(ClassFile.read(is));
try {
var clz = ClassFile.of().parse(p); // propagate IllegalArgumentException
check(clz);
} catch (IOException x) {
throw new UncheckedIOException(x);
} catch (ConstantPoolException x) {
throw new RuntimeException(x);
}
return null;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -21,21 +21,23 @@
* questions.
*/
import com.sun.tools.classfile.*;
import static com.sun.tools.classfile.AccessFlags.ACC_PRIVATE;
import static com.sun.tools.classfile.ConstantPool.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;
import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.MethodRefEntry;
import java.lang.classfile.instruction.InvokeInstruction;
import java.lang.reflect.AccessFlag;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -50,12 +52,13 @@ import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.constant.ConstantDescs.CD_Class;
/*
* @test
* @summary CallerSensitive methods should be static or final instance
* methods except the known list of non-final instance methods
* @modules jdk.jdeps/com.sun.tools.classfile
* jdk.jdeps/com.sun.tools.jdeps
* @enablePreview
* @build CheckCSMs
* @run main/othervm/timeout=900 CheckCSMs
*/
@ -66,7 +69,7 @@ public class CheckCSMs {
// The goal is to remove this list of Non-final instance @CS methods
// over time. Do not add any new one to this list.
private static Set<String> KNOWN_NON_FINAL_CSMS =
private static final Set<String> KNOWN_NON_FINAL_CSMS =
Set.of("java/io/ObjectStreamField#getType ()Ljava/lang/Class;",
"java/lang/Runtime#load (Ljava/lang/String;)V",
"java/lang/Runtime#loadLibrary (Ljava/lang/String;)V",
@ -111,119 +114,120 @@ public class CheckCSMs {
private final Set<String> nonFinalCSMs = new ConcurrentSkipListSet<>();
private final Map<String, Set<String>> csmWithCallerParameter = new ConcurrentHashMap<>();
private final ReferenceFinder finder;
public CheckCSMs() {
this.finder = new ReferenceFinder(getFilter(), getVisitor());
pool = Executors.newFixedThreadPool(numThreads);
}
public Set<String> run(Stream<Path> classes)
throws IOException, InterruptedException, ExecutionException,
ConstantPoolException
IllegalArgumentException
{
classes.forEach(p -> pool.submit(getTask(p)));
waitForCompletion();
return nonFinalCSMs;
}
private void check(ClassModel clazz) {
final String className = "jdk/internal/reflect/Reflection";
final String methodName = "getCallerClass";
boolean checkMethods = false;
for (var pe : clazz.constantPool()) {
if (pe instanceof MethodRefEntry ref
&& ref.owner().name().equalsString(className)
&& ref.name().equalsString(methodName)) {
checkMethods = true;
}
}
private ReferenceFinder.Filter getFilter() {
final String classname = "jdk/internal/reflect/Reflection";
final String method = "getCallerClass";
return new ReferenceFinder.Filter() {
public boolean accept(ConstantPool cpool, CPRefInfo cpref) {
try {
CONSTANT_NameAndType_info nat = cpref.getNameAndTypeInfo();
return cpref.getClassName().equals(classname) && nat.getName().equals(method);
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
if (!checkMethods)
return;
for (var method : clazz.methods()) {
var code = method.code().orElse(null);
if (code == null)
continue;
boolean needsCsm = false;
for (var element : code) {
if (element instanceof InvokeInstruction invoke
&& invoke.opcode() == Opcode.INVOKESTATIC
&& invoke.method() instanceof MethodRefEntry ref
&& ref.owner().name().equalsString(className)
&& ref.name().equalsString(methodName)) {
needsCsm = true;
break;
}
}
};
}
private ReferenceFinder.Visitor getVisitor() {
return new ReferenceFinder.Visitor() {
public void visit(ClassFile cf, Method m, List<CPRefInfo> refs) {
try {
// ignore jdk.unsupported/sun.reflect.Reflection.getCallerClass
// which is a "special" delegate to the internal getCallerClass
if (cf.getName().equals("sun/reflect/Reflection") &&
m.getName(cf.constant_pool).equals("getCallerClass"))
return;
String name = methodSignature(cf, m);
if (!CheckCSMs.isStaticOrFinal(cf, m, cf.constant_pool)) {
System.err.println("Unsupported @CallerSensitive: " + name);
nonFinalCSMs.add(name);
} else {
if (listCSMs) {
System.out.format("@CS %s%n", name);
}
}
// find the adapter implementation for CSM with the caller parameter
if (!csmWithCallerParameter.containsKey(cf.getName())) {
Set<String> methods = Arrays.stream(cf.methods)
.filter(m0 -> csmWithCallerParameter(cf, m, m0))
.map(m0 -> methodSignature(cf, m0))
.collect(Collectors.toSet());
csmWithCallerParameter.put(cf.getName(), methods);
}
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
}
if (needsCsm) {
process(clazz, method);
}
};
}
private static String methodSignature(ClassFile cf, Method m) {
try {
return String.format("%s#%s %s", cf.getName(),
m.getName(cf.constant_pool),
m.descriptor.getValue(cf.constant_pool));
} catch (ConstantPoolException ex) {
throw new RuntimeException(ex);
}
}
private static boolean csmWithCallerParameter(ClassFile cf, Method csm, Method m) {
ConstantPool cp = cf.constant_pool;
try {
int csmParamCount = csm.descriptor.getParameterCount(cp);
int paramCount = m.descriptor.getParameterCount(cp);
// an adapter method must have the same name and return type and a trailing Class parameter
if (!(csm.getName(cp).equals(m.getName(cp)) &&
paramCount == (csmParamCount+1) &&
m.descriptor.getReturnType(cp).equals(csm.descriptor.getReturnType(cp)))) {
private void process(ClassModel cf, MethodModel m) {
// ignore jdk.unsupported/sun.reflect.Reflection.getCallerClass
// which is a "special" delegate to the internal getCallerClass
if (cf.thisClass().name().equalsString("sun/reflect/Reflection")
&& m.methodName().equalsString("getCallerClass"))
return;
String name = methodSignature(cf, m);
if (!CheckCSMs.isStaticOrFinal(cf, m)) {
System.err.println("Unsupported @CallerSensitive: " + name);
nonFinalCSMs.add(name);
} else {
if (listCSMs) {
System.out.format("@CS %s%n", name);
}
}
// find the adapter implementation for CSM with the caller parameter
if (!csmWithCallerParameter.containsKey(cf.thisClass().asInternalName())) {
Set<String> methods = cf.methods().stream()
.filter(m0 -> csmWithCallerParameter(cf, m, m0))
.map(m0 -> methodSignature(cf, m0))
.collect(Collectors.toSet());
csmWithCallerParameter.put(cf.thisClass().asInternalName(), methods);
}
}
private static String methodSignature(ClassModel cf, MethodModel m) {
return cf.thisClass().asInternalName() + '#'
+ m.methodName().stringValue() + ' '
+ m.methodType().stringValue();
}
private static boolean csmWithCallerParameter(ClassModel cf, MethodModel csm, MethodModel m) {
var csmType = csm.methodTypeSymbol();
var mType = m.methodTypeSymbol();
// an adapter method must have the same name and return type and a trailing Class parameter
if (!(csm.methodName().equals(m.methodName()) &&
mType.parameterCount() == (csmType.parameterCount() + 1) &&
mType.returnType().equals(csmType.returnType()))) {
return false;
}
// the descriptor of the adapter method must have the parameters
// of the caller-sensitive method and an additional Class parameter
for (int i = 0; i < csmType.parameterCount(); i++) {
if (mType.parameterType(i) != csmType.parameterType(i)) {
return false;
}
// the descriptor of the adapter method must have the parameters
// of the caller-sensitive method and an additional Class parameter
String csmDesc = csm.descriptor.getParameterTypes(cp);
String desc = m.descriptor.getParameterTypes(cp);
int index = desc.indexOf(", java.lang.Class)");
if (index == -1) {
index = desc.indexOf("java.lang.Class)");
if (index == -1) return false;
}
String s = desc.substring(0, index) + ")";
if (s.equals(csmDesc)) {
if (!m.access_flags.is(ACC_PRIVATE)) {
throw new RuntimeException(methodSignature(cf, m) + " adapter method for " +
methodSignature(cf, csm) + " must be private");
}
if (!isCallerSensitiveAdapter(m, cp)) {
throw new RuntimeException(methodSignature(cf, m) + " adapter method for " +
methodSignature(cf, csm) + " must be annotated with @CallerSensitiveAdapter");
}
return true;
}
} catch (ConstantPoolException|Descriptor.InvalidDescriptor e) {
throw new RuntimeException(e);
}
return false;
if (!mType.parameterType(mType.parameterCount() - 1).equals(CD_Class)) {
return false;
}
if (!m.flags().has(AccessFlag.PRIVATE)) {
throw new RuntimeException(methodSignature(cf, m) + " adapter method for " +
methodSignature(cf, csm) + " must be private");
}
if (!isCallerSensitiveAdapter(m)) {
throw new RuntimeException(methodSignature(cf, m) + " adapter method for " +
methodSignature(cf, csm) + " must be annotated with @CallerSensitiveAdapter");
}
return true;
}
private static final String CALLER_SENSITIVE_ANNOTATION
@ -231,16 +235,13 @@ public class CheckCSMs {
private static final String CALLER_SENSITIVE_ADAPTER_ANNOTATION
= "Ljdk/internal/reflect/CallerSensitiveAdapter;";
private static boolean isCallerSensitive(Method m, ConstantPool cp)
throws ConstantPoolException
private static boolean isCallerSensitive(MethodModel m)
throws IllegalArgumentException
{
RuntimeAnnotations_attribute attr =
(RuntimeAnnotations_attribute)m.attributes.get(Attribute.RuntimeVisibleAnnotations);
var attr = m.findAttribute(Attributes.RUNTIME_VISIBLE_ANNOTATIONS).orElse(null);
if (attr != null) {
for (int i = 0; i < attr.annotations.length; i++) {
Annotation ann = attr.annotations[i];
String annType = cp.getUTF8Value(ann.type_index);
if (CALLER_SENSITIVE_ANNOTATION.equals(annType)) {
for (var ann : attr.annotations()) {
if (ann.className().equalsString(CALLER_SENSITIVE_ANNOTATION)) {
return true;
}
}
@ -248,16 +249,12 @@ public class CheckCSMs {
return false;
}
private static boolean isCallerSensitiveAdapter(Method m, ConstantPool cp)
throws ConstantPoolException
{
RuntimeAnnotations_attribute attr =
(RuntimeAnnotations_attribute)m.attributes.get(Attribute.RuntimeInvisibleAnnotations);
private static boolean isCallerSensitiveAdapter(MethodModel m) {
var attr = m.findAttribute(Attributes.RUNTIME_INVISIBLE_ANNOTATIONS).orElse(null);
if (attr != null) {
for (int i = 0; i < attr.annotations.length; i++) {
Annotation ann = attr.annotations[i];
String annType = cp.getUTF8Value(ann.type_index);
if (CALLER_SENSITIVE_ADAPTER_ANNOTATION.equals(annType)) {
for (var ann : attr.annotations()) {
if (ann.className().equalsString(CALLER_SENSITIVE_ADAPTER_ANNOTATION)) {
return true;
}
}
@ -265,16 +262,14 @@ public class CheckCSMs {
return false;
}
private static boolean isStaticOrFinal(ClassFile cf, Method m, ConstantPool cp)
throws ConstantPoolException
{
if (!isCallerSensitive(m, cp))
private static boolean isStaticOrFinal(ClassModel cf, MethodModel m) {
if (!isCallerSensitive(m))
return false;
// either a static method or a final instance method
return m.access_flags.is(AccessFlags.ACC_STATIC) ||
m.access_flags.is(AccessFlags.ACC_FINAL) ||
cf.access_flags.is(AccessFlags.ACC_FINAL);
return m.flags().has(AccessFlag.STATIC) ||
m.flags().has(AccessFlag.FINAL) ||
cf.flags().has(AccessFlag.FINAL);
}
private final List<FutureTask<Void>> tasks = new ArrayList<>();
@ -288,12 +283,11 @@ public class CheckCSMs {
private FutureTask<Void> getTask(Path p) {
FutureTask<Void> task = new FutureTask<>(new Callable<>() {
public Void call() throws Exception {
try (InputStream is = Files.newInputStream(p)) {
finder.parse(ClassFile.read(is));
try {
var clz = ClassFile.of().parse(p); // propagate IllegalArgumentException
check(clz);
} catch (IOException x) {
throw new UncheckedIOException(x);
} catch (ConstantPoolException x) {
throw new RuntimeException(x);
}
return null;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 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
@ -27,8 +27,7 @@
* @bug 8010117
* @summary Test CallerSensitiveFinder to find missing annotation
* @modules java.base/jdk.internal.reflect
* jdk.jdeps/com.sun.tools.classfile
* jdk.jdeps/com.sun.tools.jdeps
* @enablePreview
* @compile -XDignore.symbol.file MissingCallerSensitive.java
* @build CallerSensitiveFinder
* @run main MissingCallerSensitive

View File

@ -29,15 +29,17 @@
* jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.resources:open
* jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.resources:open
* jdk.javadoc/jdk.javadoc.internal.tool.resources:open
* jdk.jdeps/com.sun.tools.classfile
* @enablePreview
*/
import java.io.*;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.constantpool.Utf8Entry;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.tools.*;
import com.sun.tools.classfile.*;
/**
* Compare string constants in javadoc classes against keys in javadoc resource bundles.
@ -268,15 +270,15 @@ public class CheckResourceKeys {
//System.err.println("scan " + fo.getName());
InputStream in = fo.openInputStream();
try {
ClassFile cf = ClassFile.read(in);
for (ConstantPool.CPInfo cpinfo: cf.constant_pool.entries()) {
if (cpinfo.getTag() == ConstantPool.CONSTANT_Utf8) {
String v = ((ConstantPool.CONSTANT_Utf8_info) cpinfo).value;
ClassModel cf = ClassFile.of().parse(in.readAllBytes());
for (var cpinfo : cf.constantPool()) {
if (cpinfo instanceof Utf8Entry utf8Entry) {
String v = utf8Entry.stringValue();
if (v.matches("(doclet|main|javadoc|tag)\\.[A-Za-z0-9-_.]+"))
results.add(v);
}
}
} catch (ConstantPoolException ignore) {
} catch (IllegalArgumentException ignore) {
} finally {
in.close();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2021, 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,60 +25,66 @@
* @test
* @bug 7166455
* @summary javac doesn't set ACC_STRICT bit on <clinit> for strictfp class
* @modules jdk.jdeps/com.sun.tools.classfile
* @compile -source 16 -target 16 CheckACC_STRICTFlagOnclinitTest.java
* @run main CheckACC_STRICTFlagOnclinitTest
* @library /tools/lib /test/lib
* @enablePreview
*/
import jdk.test.lib.compiler.CompilerUtils;
import toolbox.ToolBox;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.io.IOException;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Descriptor;
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
import com.sun.tools.classfile.Method;
import static com.sun.tools.classfile.AccessFlags.ACC_STRICT;
public strictfp class CheckACC_STRICTFlagOnclinitTest {
public class CheckACC_STRICTFlagOnclinitTest {
private static final String AssertionErrorMessage =
"All methods should have the ACC_STRICT access flag " +
"please check output";
private static final String offendingMethodErrorMessage =
"Method %s of class %s doesn't have the ACC_STRICT access flag";
static {
class Foo {
class Bar {
void m11() {}
private static final String SOURCE = """
public strictfp class Test {
static {
class Foo {
class Bar {
void m11() {}
}
void m1() {}
}
}
void m2() {
class Any {
void m21() {}
}
}
}
void m1() {}
}
}
void m2() {
class Any {
void m21() {}
}
}
""";
private List<String> errors = new ArrayList<>();
private final List<String> errors = new ArrayList<>();
public static void main(String[] args)
throws IOException, ConstantPoolException, InvalidDescriptor {
throws IOException {
new CheckACC_STRICTFlagOnclinitTest().run();
}
private void run()
throws IOException, ConstantPoolException, InvalidDescriptor {
String testClasses = System.getProperty("test.classes");
check(testClasses,
"CheckACC_STRICTFlagOnclinitTest.class",
"CheckACC_STRICTFlagOnclinitTest$1Foo.class",
"CheckACC_STRICTFlagOnclinitTest$1Foo$Bar.class",
"CheckACC_STRICTFlagOnclinitTest$1Any.class");
if (errors.size() > 0) {
throws IOException {
Path in = Path.of("in");
Path out = Path.of("out");
ToolBox toolBox = new ToolBox();
toolBox.writeJavaFiles(in, SOURCE);
CompilerUtils.compile(in, out, "--release", "16");
check(out,
"Test.class",
"Test$1Foo.class",
"Test$1Foo$Bar.class",
"Test$1Any.class");
if (!errors.isEmpty()) {
for (String error: errors) {
System.err.println(error);
}
@ -86,37 +92,17 @@ public strictfp class CheckACC_STRICTFlagOnclinitTest {
}
}
void check(String dir, String... fileNames)
throws
IOException,
ConstantPoolException,
Descriptor.InvalidDescriptor {
void check(Path dir, String... fileNames) throws IOException {
for (String fileName : fileNames) {
ClassFile classFileToCheck = ClassFile.read(new File(dir, fileName));
ClassModel classFileToCheck = ClassFile.of().parse(dir.resolve(fileName));
for (Method method : classFileToCheck.methods) {
if ((method.access_flags.flags & ACC_STRICT) == 0) {
for (MethodModel method : classFileToCheck.methods()) {
if ((method.flags().flagsMask() & ClassFile.ACC_STRICT) == 0) {
errors.add(String.format(offendingMethodErrorMessage,
method.getName(classFileToCheck.constant_pool),
classFileToCheck.getName()));
method.methodName().stringValue(),
classFileToCheck.thisClass().asInternalName()));
}
}
}
}
// this version of the code can be used when ClassFile API in not in a preview
// void check(String dir, String... fileNames) throws IOException{
// for (String fileName : fileNames) {
// ClassModel classFileToCheck = ClassFile.of().parse(new File(dir, fileName).toPath());
//
// for (MethodModel method : classFileToCheck.methods()) {
// if ((method.flags().flagsMask() & ClassFile.ACC_STRICT) == 0) {
// errors.add(String.format(offendingMethodErrorMessage,
// method.methodName().stringValue(),
// classFileToCheck.thisClass().asInternalName()));
// }
// }
// }
// }
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2022, 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
@ -21,76 +21,78 @@
* questions.
*/
import com.sun.tools.classfile.*;
import com.sun.tools.classfile.BootstrapMethods_attribute.BootstrapMethodSpecifier;
import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info;
import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info;
import jdk.test.lib.compiler.CompilerUtils;
import toolbox.ToolBox;
import java.io.File;
import java.lang.classfile.Attributes;
import java.lang.classfile.BootstrapMethodEntry;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.CodeElement;
import java.lang.classfile.MethodModel;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.constantpool.MethodHandleEntry;
import java.lang.classfile.instruction.InvokeDynamicInstruction;
import java.nio.file.Path;
/*
* @test
* @bug 8148483 8151516 8151223
* @summary Test that StringConcat is working for JDK >= 9
* @modules jdk.jdeps/com.sun.tools.classfile
*
* @clean *
* @compile -source 8 -target 8 TestIndyStringConcat.java
* @run main TestIndyStringConcat false
*
* @clean *
* @compile -XDstringConcat=inline TestIndyStringConcat.java
* @run main TestIndyStringConcat false
*
* @clean *
* @compile -XDstringConcat=indy TestIndyStringConcat.java
* @run main TestIndyStringConcat true
*
* @clean *
* @compile -XDstringConcat=indyWithConstants TestIndyStringConcat.java
* @run main TestIndyStringConcat true
* @library /tools/lib /test/lib
* @enablePreview
* @run main TestIndyStringConcat
*/
public class TestIndyStringConcat {
static String other;
private static final String SOURCE = """
public class IndyStringConcat {
static String other;
public static String test() {
return "Foo" + other;
}
public static String test() {
return "Foo" + other;
}
}
""";
public static void main(String[] args) throws Exception {
boolean expected = Boolean.valueOf(args[0]);
boolean actual = hasStringConcatFactoryCall("test");
if (expected != actual) {
throw new AssertionError("expected = " + expected + ", actual = " + actual);
Path src = Path.of("src");
ToolBox toolBox = new ToolBox();
toolBox.writeJavaFiles(src, SOURCE);
int errors = 0;
errors += test(false, "java8", "-source", "8", "-target", "8");
errors += test(false, "inline", "-XDstringConcat=inline");
errors += test(true, "indy", "-XDstringConcat=indy");
errors += test(true, "indyWithConstants", "-XDstringConcat=indyWithConstants");
if (errors > 0) {
throw new AssertionError(errors + " cases failed");
}
}
public static boolean hasStringConcatFactoryCall(String methodName) throws Exception {
ClassFile classFile = ClassFile.read(new File(System.getProperty("test.classes", "."),
TestIndyStringConcat.class.getName() + ".class"));
ConstantPool constantPool = classFile.constant_pool;
public static int test(boolean expected, String label, String... args) throws Exception {
Path src = Path.of("src");
Path out = Path.of(label);
CompilerUtils.compile(src, out, args);
if (hasStringConcatFactoryCall(out.resolve("IndyStringConcat.class"), "test") != expected) {
System.err.println("Expected " + expected + " failed for case " + label);
return 1;
}
return 0;
}
BootstrapMethods_attribute bsm_attr =
(BootstrapMethods_attribute)classFile
.getAttribute(Attribute.BootstrapMethods);
public static boolean hasStringConcatFactoryCall(Path file, String methodName) throws Exception {
ClassModel classFile = ClassFile.of().parse(file);
for (Method method : classFile.methods) {
if (method.getName(constantPool).equals(methodName)) {
Code_attribute code = (Code_attribute) method.attributes
.get(Attribute.Code);
for (Instruction i : code.getInstructions()) {
if (i.getOpcode() == Opcode.INVOKEDYNAMIC) {
CONSTANT_InvokeDynamic_info indyInfo =
(CONSTANT_InvokeDynamic_info) constantPool.get(i.getUnsignedShort(1));
BootstrapMethodSpecifier bsmSpec =
bsm_attr.bootstrap_method_specifiers[indyInfo.bootstrap_method_attr_index];
CONSTANT_MethodHandle_info bsmInfo =
(CONSTANT_MethodHandle_info) constantPool.get(bsmSpec.bootstrap_method_ref);
if (bsmInfo.getCPRefInfo().getClassName().equals("java/lang/invoke/StringConcatFactory")) {
for (MethodModel method : classFile.methods()) {
if (method.methodName().equalsString(methodName)) {
CodeAttribute code = method.findAttribute(Attributes.CODE).orElseThrow();
for (CodeElement i : code.elementList()) {
if (i instanceof InvokeDynamicInstruction indy) {
BootstrapMethodEntry bsmSpec = indy.invokedynamic().bootstrap();
MethodHandleEntry bsmInfo = bsmSpec.bootstrapMethod();
if (bsmInfo.reference().owner().asInternalName().equals("java/lang/invoke/StringConcatFactory")) {
return true;
}
}
@ -100,27 +102,4 @@ public class TestIndyStringConcat {
return false;
}
// this version of the code can be used when ClassFile API in not in a preview
// public static boolean hasStringConcatFactoryCall(String methodName) throws Exception {
// ClassModel classFile = ClassFile.of().parse(new File(System.getProperty("test.classes", "."),
// TestIndyStringConcat.class.getName() + ".class").toPath());
//
// for (MethodModel method : classFile.methods()) {
// if (method.methodName().equalsString(methodName)) {
// CodeAttribute code = method.findAttribute(Attributes.CODE).orElseThrow();
// for (CodeElement i : code.elementList()) {
// if (i instanceof InvokeDynamicInstruction) {
// InvokeDynamicInstruction indy = (InvokeDynamicInstruction) i;
// BootstrapMethodEntry bsmSpec = indy.invokedynamic().bootstrap();
// MethodHandleEntry bsmInfo = bsmSpec.bootstrapMethod();
// if (bsmInfo.reference().owner().asInternalName().equals("java/lang/invoke/StringConcatFactory")) {
// return true;
// }
// }
// }
// }
// }
// return false;
// }
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2014, 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.
*/
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.SourceFile_attribute;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.tools.JavaFileObject;
import toolbox.ToolBox;
/**
* Base class for Source file attribute tests. Checks expected file name for specified classes in the SourceFile attribute.
* To add new tests you should extend the SourceFileTestBase class and invoke {@link #test} for static sources
* or {@link #compileAndTest} for generated sources. For more information see corresponding methods.
*
* @see #test
* @see #compileAndTest
*/
public class SourceFileTestBase_legacy extends TestBase {
/**
* Checks expected fileName for the specified class in the SourceFile attribute.
*
* @param classToTest class to check its SourceFile attribute
* @param fileName expected name of the file from which the test file is compiled.
*/
protected void test(Class<?> classToTest, String fileName) throws Exception {
assertAttributePresent(ClassFile.read(getClassFile(classToTest)), fileName);
}
/**
* Checks expected fileName for the specified class in the SourceFile attribute.
*
* @param classToTest class name to check its SourceFile attribute
* @param fileName expected name of the file from which the test file is compiled.
*/
protected void test(String classToTest, String fileName) throws Exception {
assertAttributePresent(ClassFile.read(getClassFile(classToTest + ".class")), fileName);
}
/**
* Checks expected fileName for the specified class in the SourceFile attribute.
*
* @param classToTest path of class to check its SourceFile attribute
* @param fileName expected name of the file from which the test file is compiled.
*/
protected void test(Path classToTest, String fileName) throws Exception {
assertAttributePresent(ClassFile.read(classToTest), fileName);
}
/**
* Compiles sourceCode and for each specified class name checks the SourceFile attribute.
* The file name is extracted from source code.
*
* @param sourceCode source code to compile
* @param classesToTest class names to check their SourceFile attribute.
*/
protected void compileAndTest(String sourceCode, String... classesToTest) throws Exception {
Map<String, ? extends JavaFileObject> classes = compile(sourceCode).getClasses();
String fileName = ToolBox.getJavaFileNameFromSource(sourceCode);
for (String className : classesToTest) {
ClassFile classFile;
try (InputStream input = classes.get(className).openInputStream()) {
classFile = ClassFile.read(input);
}
assertAttributePresent(classFile, fileName);
}
}
private void assertAttributePresent(ClassFile classFile, String fileName) throws Exception {
//We need to count attributes with the same names because there is no appropriate API in the ClassFile.
List<SourceFile_attribute> sourceFileAttributes = new ArrayList<>();
for (Attribute a : classFile.attributes.attrs) {
if (Attribute.SourceFile.equals(a.getName(classFile.constant_pool))) {
sourceFileAttributes.add((SourceFile_attribute) a);
}
}
assertEquals(sourceFileAttributes.size(), 1, "Should be the only SourceFile attribute");
SourceFile_attribute attribute = sourceFileAttributes.get(0);
assertEquals(classFile.constant_pool.getUTF8Info(attribute.attribute_name_index).value,
Attribute.SourceFile, "Incorrect attribute name");
assertEquals(classFile.constant_pool.getUTF8Info(attribute.sourcefile_index).value, fileName,
"Incorrect source file name");
assertEquals(attribute.attribute_length, 2, "Incorrect attribute length");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 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,27 +25,49 @@
* @test
* @summary sourcefile attribute test for synthetic class.
* @bug 8040129
* @library /tools/lib /tools/javac/lib ../lib_legacy
* @library /tools/lib /tools/javac/lib /test/lib ../lib
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* jdk.jdeps/com.sun.tools.classfile
* @build toolbox.ToolBox InMemoryFileManager TestBase SourceFileTestBase_legacy
* @compile -source 10 -target 10 SyntheticClassTest.java
* @run main SyntheticClassTest true
* @clean SyntheticClassTest$1
* @compile SyntheticClassTest.java
* @run main SyntheticClassTest false
* java.base/jdk.internal.classfile.impl
* @build toolbox.ToolBox InMemoryFileManager TestBase SourceFileTestBase
* @enablePreview
* @run main SyntheticClassTest
*/
import jdk.test.lib.compiler.CompilerUtils;
import toolbox.ToolBox;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
public class SyntheticClassTest extends SourceFileTestBase_legacy {
public class SyntheticClassTest extends SourceFileTestBase {
public static void main(String[] args) throws Exception {
boolean expectSynthetic = Boolean.parseBoolean(args[0]);
new Inner();
String sourceCode = """
public class SyntheticClass {
static class Inner {
private Inner() {
}
}
public SyntheticClass() {
new Inner();
}
}
""";
Path srcDir = Path.of("src");
Path v10Dir = Path.of("out10");
Path modernDir = Path.of("out");
ToolBox toolBox = new ToolBox();
toolBox.writeJavaFiles(srcDir, sourceCode);
CompilerUtils.compile(srcDir, v10Dir, "--release", "10");
CompilerUtils.compile(srcDir, modernDir);
test(v10Dir, true);
test(modernDir, false);
}
private static void test(Path path, boolean expectSynthetic) throws Exception {
try {
new SyntheticClassTest().test("SyntheticClassTest$1", "SyntheticClassTest.java");
new SyntheticClassTest().test(path.resolve("SyntheticClass$1.class"), "SyntheticClass.java");
if (!expectSynthetic) {
throw new AssertionError("Synthetic class should not have been emitted!");
}
@ -55,9 +77,4 @@ public class SyntheticClassTest extends SourceFileTestBase_legacy {
}
}
}
static class Inner {
private Inner() {
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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,12 +29,14 @@
* compiling with --release 14.
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* jdk.jdeps/com.sun.tools.classfile
* @library /tools/lib /tools/javac/lib ../lib_legacy
* @build toolbox.ToolBox InMemoryFileManager TestResult TestBase
* @build SyntheticTestDriver_legacy ExpectedClass ExpectedClasses
* @library /tools/lib /tools/javac/lib ../lib
* @build toolbox.ToolBox InMemoryFileManager
* ExpectedClass ExpectedClasses
* @compile --enable-preview --source ${jdk.version} --target ${jdk.version}
* SyntheticTestDriver.java
* ../lib/TestResult.java ../lib/TestBase.java
* @compile --source 14 -target 14 -XDdeduplicateLambdas=false BridgeMethodsForLambdaTargetRelease14Test.java
* @run main SyntheticTestDriver_legacy BridgeMethodsForLambdaTargetRelease14Test
* @run main/othervm --enable-preview SyntheticTestDriver BridgeMethodsForLambdaTargetRelease14Test
*/
import java.util.Comparator;

View File

@ -1,212 +0,0 @@
/*
* Copyright (c) 2015, 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.
*/
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.sun.tools.classfile.*;
/**
* The tests work as follows. Firstly, it looks through the test cases
* and extracts the appropriate compiled classes. Each test case contains
* a set of expected classes, methods and fields. Those class members must not have
* the Synthetic attribute, while other found classes, methods and fields must have
* the Synthetic attribute if they are not in the set of expected class members.
*
* Each test executes SyntheticTestDriver specifying the name of test cases and
* the number of expected synthetic classes. Each test class is annotated by
* annotations which contains non-synthetic class members.
*
* See the appropriate class for more information about a test case.
*/
public class SyntheticTestDriver_legacy extends TestResult {
private static final String ACC_SYNTHETIC = "ACC_SYNTHETIC";
private final String testCaseName;
private final Map<String, ClassFile> classes;
private final Map<String, ExpectedClass> expectedClasses;
public static void main(String[] args)
throws TestFailedException, ConstantPoolException, IOException, ClassNotFoundException {
if (args.length != 1 && args.length != 2) {
throw new IllegalArgumentException("Usage: SyntheticTestDriver <class-name> [<number-of-synthetic-classes>]");
}
int numberOfSyntheticClasses = args.length == 1 ? 0 : Integer.parseInt(args[1]);
new SyntheticTestDriver_legacy(args[0]).test(numberOfSyntheticClasses);
}
public SyntheticTestDriver_legacy(String testCaseName) throws IOException, ConstantPoolException, ClassNotFoundException {
Class<?> clazz = Class.forName(testCaseName);
this.testCaseName = testCaseName;
this.expectedClasses = Stream.of(clazz.getAnnotationsByType(ExpectedClass.class))
.collect(Collectors.toMap(ExpectedClass::className, Function.identity()));
this.classes = new HashMap<>();
Path classDir = getClassDir().toPath();
Pattern filePattern = Pattern.compile(Pattern.quote(testCaseName.replace('.', File.separatorChar)) + ".*\\.class");
List<Path> paths = Files.walk(classDir)
.map(p -> classDir.relativize(p.toAbsolutePath()))
.filter(p -> filePattern.matcher(p.toString()).matches())
.collect(Collectors.toList());
for (Path path : paths) {
String className = path.toString().replace(".class", "").replace(File.separatorChar, '.');
classes.put(className, readClassFile(classDir.resolve(path).toFile()));
}
if (classes.isEmpty()) {
throw new RuntimeException("Classes have not been found.");
}
boolean success = classes.entrySet().stream()
.allMatch(e -> e.getKey().startsWith(testCaseName));
if (!success) {
classes.forEach((className, $) -> printf("Found class: %s\n", className));
throw new RuntimeException("Found classes are not from the test case : " + testCaseName);
}
}
private String getMethodName(ClassFile classFile, Method method)
throws ConstantPoolException, Descriptor.InvalidDescriptor {
String methodName = method.getName(classFile.constant_pool);
String parameters = method.descriptor.getParameterTypes(classFile.constant_pool);
return methodName + parameters;
}
public void test(int expectedNumberOfSyntheticClasses) throws TestFailedException {
try {
addTestCase(testCaseName);
Set<String> foundClasses = new HashSet<>();
int numberOfSyntheticClasses = 0;
for (Map.Entry<String, ClassFile> entry : classes.entrySet()) {
String className = entry.getKey();
ClassFile classFile = entry.getValue();
foundClasses.add(className);
if (testAttribute(
classFile,
() -> (Synthetic_attribute) classFile.getAttribute(Attribute.Synthetic),
classFile.access_flags::getClassFlags,
expectedClasses.keySet(),
className,
"Testing class " + className)) {
++numberOfSyntheticClasses;
}
ExpectedClass expectedClass = expectedClasses.get(className);
Set<String> expectedMethods = expectedClass != null
? toSet(expectedClass.expectedMethods())
: new HashSet<>();
int numberOfSyntheticMethods = 0;
Set<String> foundMethods = new HashSet<>();
for (Method method : classFile.methods) {
String methodName = getMethodName(classFile, method);
foundMethods.add(methodName);
if (testAttribute(
classFile,
() -> (Synthetic_attribute) method.attributes.get(Attribute.Synthetic),
method.access_flags::getMethodFlags,
expectedMethods,
methodName,
"Testing method " + methodName + " in class "
+ className)) {
++numberOfSyntheticMethods;
}
}
checkContains(foundMethods, expectedMethods,
"Checking that all methods of class " + className
+ " without Synthetic attribute have been found");
checkEquals(numberOfSyntheticMethods,
expectedClass == null ? 0 : expectedClass.expectedNumberOfSyntheticMethods(),
"Checking number of synthetic methods in class: " + className);
Set<String> expectedFields = expectedClass != null
? toSet(expectedClass.expectedFields())
: new HashSet<>();
int numberOfSyntheticFields = 0;
Set<String> foundFields = new HashSet<>();
for (Field field : classFile.fields) {
String fieldName = field.getName(classFile.constant_pool);
foundFields.add(fieldName);
if (testAttribute(
classFile,
() -> (Synthetic_attribute) field.attributes.get(Attribute.Synthetic),
field.access_flags::getFieldFlags,
expectedFields,
fieldName,
"Testing field " + fieldName + " in class "
+ className)) {
++numberOfSyntheticFields;
}
}
checkContains(foundFields, expectedFields,
"Checking that all fields of class " + className
+ " without Synthetic attribute have been found");
checkEquals(numberOfSyntheticFields,
expectedClass == null ? 0 : expectedClass.expectedNumberOfSyntheticFields(),
"Checking number of synthetic fields in class: " + className);
}
checkContains(foundClasses, expectedClasses.keySet(),
"Checking that all classes have been found");
checkEquals(numberOfSyntheticClasses, expectedNumberOfSyntheticClasses,
"Checking number of synthetic classes");
} catch (Exception e) {
addFailure(e);
} finally {
checkStatus();
}
}
private boolean testAttribute(ClassFile classFile,
Supplier<Synthetic_attribute> getSyntheticAttribute,
Supplier<Set<String>> getAccessFlags,
Set<String> expectedMembers, String memberName,
String info) throws ConstantPoolException {
echo(info);
String className = classFile.getName();
Synthetic_attribute attr = getSyntheticAttribute.get();
Set<String> flags = getAccessFlags.get();
if (expectedMembers.contains(memberName)) {
checkNull(attr, "Member must not have synthetic attribute : "
+ memberName);
checkFalse(flags.contains(ACC_SYNTHETIC),
"Member must not have synthetic flag : " + memberName
+ " in class : " + className);
return false;
} else {
return checkNull(attr, "Synthetic attribute should not be generated")
&& checkTrue(flags.contains(ACC_SYNTHETIC), "Member must have synthetic flag : "
+ memberName + " in class : " + className);
}
}
private Set<String> toSet(String[] strings) {
HashSet<String> set = new HashSet<>();
Collections.addAll(set, strings);
return set;
}
}

View File

@ -1,284 +0,0 @@
/*
* Copyright (c) 2014, 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.
*/
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import toolbox.JavacTask;
import toolbox.ToolBox;
/**
* Base class for class file attribute tests.
* Contains methods for compiling generated sources in memory,
* for reading files from disk and a lot of assert* methods.
*/
public class TestBase {
public static final String LINE_SEPARATOR = System.lineSeparator();
public static final boolean isDumpOfSourceEnabled = Boolean.getBoolean("dump.src");
private <S> InMemoryFileManager compile(
List<String> options,
Function<S, ? extends JavaFileObject> src2JavaFileObject,
List<S> sources)
throws IOException, CompilationException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<? extends JavaFileObject> src = sources.stream()
.map(src2JavaFileObject)
.collect(Collectors.toList());
DiagnosticCollector<? super JavaFileObject> dc = new DiagnosticCollector<>();
try (InMemoryFileManager fileManager
= new InMemoryFileManager(compiler.getStandardFileManager(null, null, null))) {
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, dc, options, null, src);
boolean success = task.call();
if (!success) {
String errorMessage = dc.getDiagnostics().stream()
.map(Object::toString)
.collect(Collectors.joining("\n"));
throw new CompilationException("Compilation Error\n\n" + errorMessage);
}
return fileManager;
}
}
/**
* Compiles sources in memory.
*
* @param sources to compile
* @return in-memory file manager which contains class files and class loader
*/
public InMemoryFileManager compile(String... sources)
throws IOException, CompilationException {
return compile(Collections.emptyList(), sources);
}
/**
* Compiles sources in memory.
*
* @param options compiler options.
* @param sources sources to compile.
* @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String... sources)
throws IOException, CompilationException {
return compile(options, ToolBox.JavaSource::new, Arrays.asList(sources));
}
/**
* Compiles sources in memory.
*
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
* @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(String[]... sources) throws IOException,
CompilationException {
return compile(Collections.emptyList(), sources);
}
/**
* Compiles sources in memory.
*
* @param options compiler options
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
* @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String[]... sources)
throws IOException, CompilationException {
return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), Arrays.asList(sources));
}
/**
* Returns class file that is read from {@code is}.
*
* @param is an input stream
* @return class file that is read from {@code is}
* @throws IOException if I/O error occurs
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(InputStream is) throws IOException, ConstantPoolException {
return ClassFile.read(is);
}
/**
* Returns class file that is read from {@code fileObject}.
*
* @param fileObject a file object
* @return class file that is read from {@code fileObject}
* @throws IOException if I/O error occurs
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException {
try (InputStream is = fileObject.openInputStream()) {
return readClassFile(is);
}
}
/**
* Returns class file that corresponds to {@code clazz}.
*
* @param clazz a class
* @return class file that is read from {@code clazz}
* @throws IOException if I/O error occurs
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(Class<?> clazz) throws IOException, ConstantPoolException {
return readClassFile(getClassFile(clazz));
}
/**
* Returns class file that corresponds to {@code className}.
*
* @param className a class name
* @return class file that is read from {@code className}
* @throws IOException if I/O error occurs
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(String className) throws IOException, ConstantPoolException {
return readClassFile(getClassFile(className + ".class"));
}
/**
* Returns class file that is read from {@code file}.
*
* @param file a file
* @return class file that is read from {@code file}
* @throws IOException if I/O error occurs
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(File file) throws IOException, ConstantPoolException {
try (InputStream is = new FileInputStream(file)) {
return readClassFile(is);
}
}
public void assertEquals(Object actual, Object expected, String message) {
if (!Objects.equals(actual, expected))
throw new AssertionFailedException(String.format("%s%nGot: %s, Expected: %s",
message, actual, expected));
}
public void assertNull(Object actual, String message) {
assertEquals(actual, null, message);
}
public void assertNotNull(Object actual, String message) {
if (Objects.isNull(actual)) {
throw new AssertionFailedException(message + " : Expected not null value");
}
}
public void assertTrue(boolean actual, String message) {
assertEquals(actual, true, message);
}
public void assertFalse(boolean actual, String message) {
assertEquals(actual, false, message);
}
public void assertContains(Set<?> found, Set<?> expected, String message) {
Set<?> copy = new HashSet<>(expected);
copy.removeAll(found);
assertTrue(found.containsAll(expected), message + " : " + copy);
}
public void writeToFile(Path path, String source) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(path)) {
writer.write(source);
}
}
public void writeToFileIfEnabled(Path path, String source) throws IOException {
if (isDumpOfSourceEnabled) {
writeToFile(path, source);
} else {
System.err.println("Source dumping disabled. To enable, run the test with '-Ddump.src=true'");
}
}
public File getSourceDir() {
return new File(System.getProperty("test.src", "."));
}
public File getClassDir() {
return new File(System.getProperty("test.classes", TestBase.class.getResource(".").getPath()));
}
public File getSourceFile(String fileName) {
return new File(getSourceDir(), fileName);
}
public File getClassFile(String fileName) {
return new File(getClassDir(), fileName);
}
public File getClassFile(Class clazz) {
return getClassFile(clazz.getName().replace(".", "/") + ".class");
}
/**
* Prints message to standard error. New lines are converted to system dependent NL.
*
* @param message string to print.
*/
public void echo(String message) {
printf(message + "\n");
}
/**
* Substitutes args in template and prints result to standard error.
* New lines are converted to system dependent NL.
*
* @param template template in standard String.format(...) format.
* @param args arguments to substitute in template.
*/
public void printf(String template, Object... args) {
System.err.printf(String.format(template, args).replace("\n", LINE_SEPARATOR));
}
public static class CompilationException extends Exception {
public CompilationException(String message) {
super(message);
}
}
public static class AssertionFailedException extends RuntimeException {
public AssertionFailedException(String message) {
super(message);
}
}
}

View File

@ -1,191 +0,0 @@
/*
* Copyright (c) 2014, 2017, 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.
*/
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
/**
* This class accumulates test results. Test results can be checked with method {@code checkStatus}.
*/
public class TestResult extends TestBase {
private final List<Info> testCasesInfo;
public TestResult() {
testCasesInfo = new ArrayList<>();
}
/**
* Adds new test case info.
*
* @param info the information about test case
*/
public void addTestCase(String info) {
System.err.println("Test case: " + info);
testCasesInfo.add(new Info(info));
}
public boolean checkEquals(Object actual, Object expected, String message) {
echo("Testing : " + message);
if (!Objects.equals(actual, expected)) {
getLastTestCase().addAssert(String.format("%s\n" +
"Expected: %s,\n" +
" Got: %s", message, expected, actual));
return false;
}
return true;
}
public boolean checkNull(Object actual, String message) {
return checkEquals(actual, null, message);
}
public boolean checkNotNull(Object actual, String message) {
echo("Testing : " + message);
if (Objects.isNull(actual)) {
getLastTestCase().addAssert(message + " : Expected not null value");
return false;
}
return true;
}
public boolean checkFalse(boolean actual, String message) {
return checkEquals(actual, false, message);
}
public boolean checkTrue(boolean actual, String message) {
return checkEquals(actual, true, message);
}
public boolean checkContains(Collection<?> found, Collection<?> expected, String message) {
Set<?> copy = new HashSet<>(expected);
copy.removeAll(found);
if (!found.containsAll(expected)) {
return checkTrue(false, message + " FAIL : not found elements : " + copy + "\n" +
"Actual: " + found);
} else {
return checkTrue(true, message + " PASS : all elements found");
}
}
public void addFailure(Throwable th) {
if (testCasesInfo.isEmpty()) {
testCasesInfo.add(new Info("Dummy info"));
}
getLastTestCase().addFailure(th);
}
private Info getLastTestCase() {
if (testCasesInfo.isEmpty()) {
throw new IllegalStateException("Test case should be created");
}
return testCasesInfo.get(testCasesInfo.size() - 1);
}
/**
* Throws {@code TestFailedException} if one of the checks are failed
* or an exception occurs. Prints error message of failed test cases.
*
* @throws TestFailedException if one of the checks are failed
* or an exception occurs
*/
public void checkStatus() throws TestFailedException {
int passed = 0;
int failed = 0;
for (Info testCaseInfo : testCasesInfo) {
if (testCaseInfo.isFailed()) {
String info = testCaseInfo.info().replace("\n", LINE_SEPARATOR);
String errorMessage = testCaseInfo.getMessage().replace("\n", LINE_SEPARATOR);
System.err.printf("Failure in test case:%n%s%n%s%n", info, errorMessage);
++failed;
} else {
++passed;
}
}
System.err.printf("Test cases: passed: %d, failed: %d, total: %d.%n", passed, failed, passed + failed);
if (failed > 0) {
throw new TestFailedException("Test failed");
}
if (passed + failed == 0) {
throw new TestFailedException("Test cases were not found");
}
}
@Override
public void printf(String template, Object... args) {
getLastTestCase().printf(template, args);
}
private static class Info {
private final String info;
private final StringWriter writer;
private boolean isFailed;
private Info(String info) {
this.info = info;
writer = new StringWriter();
}
public String info() {
return info;
}
public boolean isFailed() {
return isFailed;
}
public void printf(String template, Object... args) {
writer.write(String.format(template, args));
}
public void addFailure(Throwable th) {
isFailed = true;
printf("[ERROR] : %s\n", getStackTrace(th));
}
public void addAssert(String e) {
isFailed = true;
printf("[ASSERT] : %s\n", e);
}
public String getMessage() {
return writer.toString();
}
public String getStackTrace(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
try (PrintWriter printWriter = new PrintWriter(stringWriter)) {
throwable.printStackTrace(printWriter);
}
return stringWriter.toString();
}
}
public static class TestFailedException extends Exception {
public TestFailedException(String message) {
super(message);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2021, 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,44 +25,51 @@
* @test
* @bug 8012723
* @summary strictfp interface misses strictfp modifer on default method
* @modules jdk.jdeps/com.sun.tools.classfile
* @compile -source 16 -target 16 CheckACC_STRICTFlagOnDefaultMethodTest.java
* @library /tools/lib /test/lib
* @enablePreview
* @run main CheckACC_STRICTFlagOnDefaultMethodTest
*/
import jdk.test.lib.compiler.CompilerUtils;
import toolbox.ToolBox;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.io.IOException;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Descriptor;
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
import com.sun.tools.classfile.Method;
import static com.sun.tools.classfile.AccessFlags.ACC_STRICT;
public class CheckACC_STRICTFlagOnDefaultMethodTest {
private static final String AssertionErrorMessage =
"All methods should have the ACC_STRICT access flag " +
"please check output";
private static final String offendingMethodErrorMessage =
"Method %s of class %s doesn't have the ACC_STRICT access flag";
private static final String SOURCE = """
strictfp interface StrictfpInterface {
default void default_interface_method() {}
static void static_interface_method() {}
}
""";
private List<String> errors = new ArrayList<>();
public static void main(String[] args)
throws IOException, ConstantPoolException, InvalidDescriptor {
throws IOException {
new CheckACC_STRICTFlagOnDefaultMethodTest().run();
}
private void run()
throws IOException, ConstantPoolException, InvalidDescriptor {
String testClasses = System.getProperty("test.classes");
check(testClasses,
"CheckACC_STRICTFlagOnDefaultMethodTest$StrictfpInterface.class");
if (errors.size() > 0) {
throws IOException {
Path src = Path.of("src");
Path out = Path.of("out");
ToolBox toolBox = new ToolBox();
toolBox.writeJavaFiles(src, SOURCE);
CompilerUtils.compile(src, out, "--release", "16");
check(out, "StrictfpInterface.class");
if (!errors.isEmpty()) {
for (String error: errors) {
System.err.println(error);
}
@ -70,42 +77,17 @@ public class CheckACC_STRICTFlagOnDefaultMethodTest {
}
}
void check(String dir, String... fileNames)
throws
IOException,
ConstantPoolException,
Descriptor.InvalidDescriptor {
void check(Path dir, String... fileNames) throws IOException {
for (String fileName : fileNames) {
ClassFile classFileToCheck = ClassFile.read(new File(dir, fileName));
ClassModel classFileToCheck = ClassFile.of().parse(dir.resolve(fileName));
for (Method method : classFileToCheck.methods) {
if ((method.access_flags.flags & ACC_STRICT) == 0) {
for (MethodModel method : classFileToCheck.methods()) {
if ((method.flags().flagsMask() & ClassFile.ACC_STRICT) == 0) {
errors.add(String.format(offendingMethodErrorMessage,
method.getName(classFileToCheck.constant_pool),
classFileToCheck.getName()));
method.methodName().stringValue(),
classFileToCheck.thisClass().asInternalName()));
}
}
}
}
// this version of the code can be used when ClassFile API in not in a preview
// void check(String dir, String... fileNames) throws IOException {
// for (String fileName : fileNames) {
// ClassModel classFileToCheck = ClassFile.of().parse(new File(dir, fileName).toPath());
//
// for (MethodModel method : classFileToCheck.methods()) {
// if ((method.flags().flagsMask() & ClassFile.ACC_STRICT) == 0) {
// errors.add(String.format(offendingMethodErrorMessage,
// method.methodName().stringValue(),
// classFileToCheck.thisClass().asInternalName()));
// }
// }
// }
// }
strictfp interface StrictfpInterface {
default void default_interface_method() {}
static void static_interface_method() {}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 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,27 +25,49 @@
* @test
* @bug 8046060
* @summary Different results of floating point multiplication for lambda code block
* @modules jdk.jdeps/com.sun.tools.classfile
* @compile -source 16 -target 16 LambdaTestStrictFPFlag.java
* @library /tools/lib /test/lib
* @enablePreview
* @run main LambdaTestStrictFPFlag
*/
import java.io.*;
import java.net.URL;
import com.sun.tools.classfile.*;
import jdk.test.lib.compiler.CompilerUtils;
import toolbox.ToolBox;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.MethodModel;
import java.nio.file.Path;
public class LambdaTestStrictFPFlag {
private static final String SOURCE = """
class Test {
strictfp void test() {
Face itf = () -> { };
}
}
interface Face {
void m();
}
""";
public static void main(String[] args) throws Exception {
new LambdaTestStrictFPFlag().run();
}
void run() throws Exception {
ClassFile cf = getClassFile("LambdaTestStrictFPFlag$Test.class");
ConstantPool cp = cf.constant_pool;
Path src = Path.of("src");
Path out = Path.of("out");
ToolBox toolBox = new ToolBox();
toolBox.writeJavaFiles(src, SOURCE);
CompilerUtils.compile(src, out, "--release", "16");
ClassModel cm = ClassFile.of().parse(out.resolve("Test.class"));
boolean found = false;
for (Method meth: cf.methods) {
if (meth.getName(cp).startsWith("lambda$")) {
if ((meth.access_flags.flags & AccessFlags.ACC_STRICT) == 0) {
for (MethodModel meth: cm.methods()) {
if (meth.methodName().stringValue().startsWith("lambda$")) {
if ((meth.flags().flagsMask() & ClassFile.ACC_STRICT) == 0){
throw new Exception("strict flag missing from lambda");
}
found = true;
@ -55,41 +77,4 @@ public class LambdaTestStrictFPFlag {
throw new Exception("did not find lambda method");
}
}
// this version of the code can be used when ClassFile API in not in a preview
// void run() throws Exception {
// ClassModel cm = getClassFile("LambdaTestStrictFPFlag$Test.class");
// boolean found = false;
// for (MethodModel meth: cm.methods()) {
// if (meth.methodName().stringValue().startsWith("lambda$")) {
// if ((meth.flags().flagsMask() & ClassFile.ACC_STRICT) == 0){
// throw new Exception("strict flag missing from lambda");
// }
// found = true;
// }
// }
// if (!found) {
// throw new Exception("did not find lambda method");
// }
// }
ClassFile getClassFile(String name) throws IOException, ConstantPoolException {
URL url = getClass().getResource(name);
InputStream in = url.openStream();
try {
return ClassFile.read(in);
} finally {
in.close();
}
}
class Test {
strictfp void test() {
Face itf = () -> { };
}
}
interface Face {
void m();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2016, 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
@ -25,12 +25,10 @@
* @test
* @bug 6866657
* @summary add byteLength() method to primary classfile types
* @modules jdk.jdeps/com.sun.tools.classfile
* jdk.jdeps/com.sun.tools.javap
* @modules jdk.jdeps/com.sun.tools.javap
*/
import java.io.*;
import java.util.*;
import javax.tools.*;
import com.sun.tools.javap.*;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, 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,12 +25,9 @@
* @test
* @bug 7186925
* @summary JavapTask passes null to java.io.Writer
* @modules jdk.jdeps/com.sun.tools.classfile
* jdk.jdeps/com.sun.tools.javap
* @modules jdk.jdeps/com.sun.tools.javap
*/
import java.io.*;
import java.util.*;
import javax.tools.*;
import com.sun.tools.javap.*;

View File

@ -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,7 +28,6 @@
* @library lib
* @modules java.base/sun.security.x509
* java.management
* jdk.jdeps/com.sun.tools.classfile
* jdk.jdeps/com.sun.tools.jdeps
* @run main APIDeps
*/
@ -104,17 +103,17 @@ public class APIDeps {
new String[] {"c.I", "e.E", "f.F", "m.Bar"},
new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-filter:none"});
test(new File(mDir, "Gee.class"),
new String[] {"g.G", "sun.security.x509.X509CertInfo", "com.sun.tools.classfile.ClassFile",
new String[] {"g.G", "sun.security.x509.X509CertInfo", "com.sun.tools.jdeps.Analyzer",
"com.sun.management.ThreadMXBean", "com.sun.source.tree.BinaryTree"},
new String[] {"-classpath", testDir.getPath(), "-verbose"});
// -jdkinternals
test(new File(mDir, "Gee.class"),
new String[] {"sun.security.x509.X509CertInfo", "com.sun.tools.classfile.ClassFile"},
new String[] {"sun.security.x509.X509CertInfo", "com.sun.tools.jdeps.Analyzer"},
new String[] {"-jdkinternals", "-quiet"});
// -jdkinternals parses all classes on -classpath and the input arguments
test(new File(mDir, "Gee.class"),
new String[] {"com.sun.tools.classfile.ClassFile",
new String[] {"com.sun.tools.jdeps.Analyzer",
"sun.security.x509.X509CertInfo"},
// use -classpath tmp/a with no use of JDK internal API
new String[] {"-classpath", dest.resolve("a").toString(), "-jdkinternals", "-quiet"});

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2014, 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
@ -26,7 +26,7 @@ package m;
class Gee extends g.G {
public sun.security.x509.X509CertInfo cert;
public com.sun.tools.classfile.ClassFile cf; // not exported
public com.sun.tools.jdeps.Analyzer analyzer; // not exported
public com.sun.source.tree.BinaryTree tree; // exported
public com.sun.management.ThreadMXBean mxbean; // exported
}