This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-bcel.git
The following commit(s) were added to refs/heads/master by this push:
new 32214443 ```text (#537)
32214443 is described below
commit 32214443f0a890bde33b0c7886637b48db197fcc
Author: Gary Gregory <[email protected]>
AuthorDate: Sun Oct 18 08:54:58 2026 -0400
```text (#537)
Update ECJ versions and generate the SWAP fixture with BCEL
Default ecj.version to 3.46.100. Add property-only Maven profiles
selecting 3.33.0 on Java 11 and below and 3.26.0 on Java 8 and below,
with the Java 8 profile taking precedence when both activate.
Replace Java 1.4 compilation in VerifierMainTest with BCEL-generated
bytecode containing a SWAP instruction. Current ECJ releases reject
the old source level, leaving the expected class file missing.
Remove the unused SWAP.java fixture.
Run the verifier subprocess with the current Java runtime and prepend
the temporary fixture directory to its classpath. Retain assertions
for successful verification and exactly one SWAP instruction, and
dispose of instruction lists after use.
---
pom.xml | 25 ++++++++--
src/test/java/org/apache/bcel/data/SWAP.java | 39 ---------------
.../org/apache/bcel/verifier/VerifierMainTest.java | 55 +++++++++++++++++-----
3 files changed, 64 insertions(+), 55 deletions(-)
diff --git a/pom.xml b/pom.xml
index ac1ac5e9..dc0f8232 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,9 +59,7 @@
<commons.jira.pid>12314220</commons.jira.pid>
<jna.version>5.19.1</jna.version>
<japicmp.skip>false</japicmp.skip>
- <!-- 3.26.0 is the last JDK8-compatible version -->
- <!-- 3.27.0 says "class file has wrong version 55.0, should be 52.0" -->
- <ecj.version>3.26.0</ecj.version>
+ <ecj.version>3.46.100</ecj.version>
<!-- JaCoCo on Java 8 is different from other versions. On JDK9+ there is
a profile -->
<!-- JaCoCo: Don't make code coverage worse than: -->
<commons.jacoco.haltOnFailure>true</commons.jacoco.haltOnFailure>
@@ -497,6 +495,27 @@
</plugins>
</build>
</profile>
+ <profile>
+ <id>ecj-java-11-down</id>
+ <activation>
+ <jdk>(,12)</jdk>
+ </activation>
+ <properties>
+ <!-- Last ECJ version compatible with Java 11. -->
+ <ecj.version>3.33.0</ecj.version>
+ </properties>
+ </profile>
+ <!-- Keep this profile after ecj-java-11-down so its property takes
precedence on Java 8 and below. -->
+ <profile>
+ <id>ecj-java-8-down</id>
+ <activation>
+ <jdk>(,1.9)</jdk>
+ </activation>
+ <properties>
+ <!-- Last ECJ version compatible with Java 8. -->
+ <ecj.version>3.26.0</ecj.version>
+ </properties>
+ </profile>
<profile>
<id>spdx-java-11</id>
<activation>
diff --git a/src/test/java/org/apache/bcel/data/SWAP.java
b/src/test/java/org/apache/bcel/data/SWAP.java
deleted file mode 100644
index cb0ac82a..00000000
--- a/src/test/java/org/apache/bcel/data/SWAP.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.bcel.data;
-
-import java.lang.reflect.Constructor;
-
-/*
- * A test for SWAP instruction.
- * To be compiled with Eclipse Compiler (ecj) with source/target 1.4.
- * This is a requirement for SWAP instruction to be generated.
- * If compiled with javac source/target 1.1+ or ecj source/target 1.5+, no
SWAP instruction is generated.
- */
-public class SWAP {
- public static Constructor getTestConstructor(final Class theClass) throws
NoSuchMethodException {
- final Class[] args = { String.class };
- try {
- return theClass.getConstructor(args);
- } catch (final NoSuchMethodException e) {
- }
- return theClass.getConstructor(new Class[0]);
- }
-}
diff --git a/src/test/java/org/apache/bcel/verifier/VerifierMainTest.java
b/src/test/java/org/apache/bcel/verifier/VerifierMainTest.java
index e6f490b6..a2938ad3 100644
--- a/src/test/java/org/apache/bcel/verifier/VerifierMainTest.java
+++ b/src/test/java/org/apache/bcel/verifier/VerifierMainTest.java
@@ -22,24 +22,29 @@ package org.apache.bcel.verifier;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.BufferedInputStream;
+import java.io.File;
import java.io.InputStream;
-import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.apache.bcel.AbstractTest;
+import org.apache.bcel.Const;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.EmptyVisitor;
+import org.apache.bcel.generic.ILOAD;
+import org.apache.bcel.generic.InstructionConst;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.SWAP;
+import org.apache.bcel.generic.Type;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemProperties;
-import org.eclipse.jdt.internal.compiler.batch.Main;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@@ -50,16 +55,36 @@ class VerifierMainTest extends AbstractTest {
@Test
void testSWAP() throws Exception {
- final String[] argv = {
"src/test/java/org/apache/bcel/data/SWAP.java", "-g", "-source", "1.4",
"-target", "1.4", "-d", tempDir.toString() };
- new Main(new PrintWriter(System.out), new PrintWriter(System.err),
false/*systemExit*/, null/*options*/, null/*progress*/).compile(argv);
+ final String className = "org.apache.bcel.data.SWAP";
+ final Path classFile =
tempDir.resolve("org/apache/bcel/data/SWAP.class");
+ final ClassGen classGen = new ClassGen(className, "java.lang.Object",
"SWAP.java", Const.ACC_PUBLIC | Const.ACC_SUPER, null);
+ classGen.setMajor(Const.MAJOR_1_4);
+ classGen.setMinor(Const.MINOR_1_4);
+ classGen.addEmptyConstructor(Const.ACC_PUBLIC);
+ final InstructionList instructions = new InstructionList();
+ try {
+ instructions.append(new ILOAD(0));
+ instructions.append(new ILOAD(1));
+ instructions.append(InstructionConst.SWAP);
+ instructions.append(InstructionConst.ISUB);
+ instructions.append(InstructionConst.IRETURN);
+ final MethodGen methodGen = new MethodGen(Const.ACC_PUBLIC |
Const.ACC_STATIC, Type.INT, new Type[] { Type.INT, Type.INT },
+ new String[] { "first", "second" }, "swap", className,
instructions, classGen.getConstantPool());
+ methodGen.setMaxStack();
+ methodGen.setMaxLocals();
+ classGen.addMethod(methodGen.getMethod());
+ } finally {
+ instructions.dispose();
+ }
+ classGen.getJavaClass().dump(classFile.toFile());
final String javaAgent = getJavaAgent();
final List<String> args = new ArrayList<>();
- args.add("java");
+ args.add(SystemProperties.getJavaHome() + File.separator + "bin" +
File.separator + "java");
if (javaAgent != null) {
args.add(javaAgent.replace("jacoco.exec",
"jacoco_org.apache.bcel.data.SWAP.exec"));
}
args.add("-cp");
- args.add(SystemProperties.getJavaClassPath());
+ args.add(tempDir + File.pathSeparator +
SystemProperties.getJavaClassPath());
args.add("org.apache.bcel.verifier.Verifier");
args.add("org/apache/bcel/data/SWAP.class");
final ProcessBuilder pb = new ProcessBuilder(args);
@@ -76,7 +101,7 @@ class VerifierMainTest extends AbstractTest {
assertEquals(0, StringUtils.countMatches(output,
"VERIFIED_REJECTED"), output);
assertEquals(6, StringUtils.countMatches(output, "VERIFIED_OK"),
output);
}
- // Class has passed the JustIce verifier, but now we need to ensure
that the SWAP instruction is in the compiled class.
+ // Class has passed the JustIce verifier, but now we need to ensure
that the SWAP instruction is in the generated class.
final List<SWAP> swapInstructionsList = new ArrayList<>();
final EmptyVisitor swapCollector = new EmptyVisitor() {
@Override
@@ -85,14 +110,18 @@ class VerifierMainTest extends AbstractTest {
super.visitSWAP(obj);
}
};
- try (InputStream in =
Files.newInputStream(tempDir.resolve("org/apache/bcel/data/SWAP.class"))) {
+ try (InputStream in = Files.newInputStream(classFile)) {
final ClassParser classParser = new ClassParser(in, "SWAP.class");
final JavaClass javaClass = classParser.parse();
- final Method method =
javaClass.getMethod(org.apache.bcel.data.SWAP.class.getMethod("getTestConstructor",
Class.class));
- final byte[] code = method.getCode().getCode();
- final InstructionList instructionList = new InstructionList(code);
- for (final InstructionHandle instructionHandle : instructionList) {
- instructionHandle.accept(swapCollector);
+ for (final Method method : javaClass.getMethods()) {
+ final InstructionList instructionList = new
InstructionList(method.getCode().getCode());
+ try {
+ for (final InstructionHandle instructionHandle :
instructionList) {
+ instructionHandle.accept(swapCollector);
+ }
+ } finally {
+ instructionList.dispose();
+ }
}
}
assertEquals(1, swapInstructionsList.size());