Skip to content

Commit c6f20aa

Browse files
authored
Support running on JDK 17 (#1281)
With this change, WALA's regression tests pass on JDK 17, and WALA can also load and process some JDK 17 bytecodes. We have _not_ thoroughly tested recent bytecode features and they may still not work, but whatever is exercised by current regression tests seems to be working. Getting things working on JDK 17 required various minor changes.
1 parent 6f9e6ce commit c6f20aa

File tree

12 files changed

+73
-48
lines changed

12 files changed

+73
-48
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ jobs:
1919
java: 11
2020
- os: windows-latest
2121
java: 11
22+
- os: ubuntu-latest
23+
java: 17
2224
fail-fast: false
2325
runs-on: ${{ matrix.os }}
2426
steps:

build-logic/src/main/kotlin/com/ibm/wala/gradle/java.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ dependencies {
4343
"javadocSource"(sourceSets.main.get().allJava)
4444
}
4545

46-
the<JavaPluginExtension>().toolchain.languageVersion.set(JavaLanguageVersion.of(11))
47-
4846
tasks.withType<JavaCompile>().configureEach {
47+
// Generate JDK 11 bytecodes; that is the minimum version supported by WALA
48+
options.release.set(11)
4949
options.errorprone {
5050
// don't run warning-level checks by default as they add too much noise to build output
5151
// NOTE: until https://github.com/google/error-prone/pull/3462 makes it to a release,

cast/java/src/testFixtures/java/com/ibm/wala/cast/java/test/JavaIRTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ public void testMiniaturSliceBug() throws IllegalArgumentException, CancelExcept
722722
AstJavaSlicer.computeAssertionSlice(cg, pa, roots, false);
723723
Collection<Statement> slice = y.fst;
724724
dumpSlice(slice);
725-
Assert.assertEquals(0, SlicerUtil.countAllocations(slice));
725+
Assert.assertEquals(0, SlicerUtil.countAllocations(slice, false));
726726
Assert.assertEquals(1, SlicerUtil.countPutfields(slice));
727727

728728
// test slice from main
@@ -731,7 +731,7 @@ public void testMiniaturSliceBug() throws IllegalArgumentException, CancelExcept
731731
y = AstJavaSlicer.computeAssertionSlice(cg, pa, roots, false);
732732
slice = y.fst;
733733
// SlicerUtil.dumpSlice(slice);
734-
Assert.assertEquals(2, SlicerUtil.countAllocations(slice));
734+
Assert.assertEquals(2, SlicerUtil.countAllocations(slice, false));
735735
Assert.assertEquals(2, SlicerUtil.countPutfields(slice));
736736
}
737737

cast/java/test/data/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,9 @@ sourceSets.test.get().java.srcDir(downloadJLex.map { it.extra["downloadedSourceD
5959
//
6060

6161
tasks.register("prepareMavenBuild") { dependsOn("eclipseClasspath", "eclipseProject") }
62+
63+
// On JDK 17, deprecation errors in ECJ cannot be disabled when compiling JLex code. So, we disable
64+
// the ECJ task on JDK 17+.
65+
if (JavaVersion.current() >= JavaVersion.VERSION_17) {
66+
tasks.named("compileTestJavaUsingEcj") { enabled = false }
67+
}

core/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ tasks.named<Copy>("processTestResources") {
347347
}
348348

349349
tasks.named<Test>("test") {
350-
maxHeapSize = "1500M"
350+
maxHeapSize = "2000M"
351351
systemProperty("com.ibm.wala.junit.profile", "short")
352352
classpath += files(sourceSets.test.get().output.classesDirs)
353353
testLogging {

core/src/main/java/com/ibm/wala/analysis/exceptionanalysis/ExceptionAnalysis.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.ibm.wala.analysis.arraybounds.ArrayOutOfBoundsAnalysis;
1414
import com.ibm.wala.analysis.nullpointer.IntraproceduralNullPointerAnalysis;
1515
import com.ibm.wala.classLoader.CallSiteReference;
16+
import com.ibm.wala.classLoader.IClass;
1617
import com.ibm.wala.dataflow.graph.BitVectorFramework;
1718
import com.ibm.wala.dataflow.graph.BitVectorSolver;
1819
import com.ibm.wala.fixpoint.BitVectorVariable;
@@ -127,10 +128,18 @@ public boolean catchesException(
127128
boolean isCaught = false;
128129
while (caughtExceptions.hasNext() && !isCaught) {
129130
TypeReference caughtException = caughtExceptions.next();
131+
IClass caughtExceptionClass = cha.lookupClass(caughtException);
132+
if (caughtExceptionClass == null) {
133+
// for now, assume it is not caught
134+
continue;
135+
}
130136
for (TypeReference thrownException : thrownExceptions) {
131-
isCaught |=
132-
cha.isAssignableFrom(
133-
cha.lookupClass(caughtException), cha.lookupClass(thrownException));
137+
IClass thrownExceptionClass = cha.lookupClass(thrownException);
138+
if (thrownExceptionClass == null) {
139+
// for now, assume it is not caught
140+
continue;
141+
}
142+
isCaught |= cha.isAssignableFrom(caughtExceptionClass, thrownExceptionClass);
134143
if (isCaught) break;
135144
}
136145
}

core/src/main/java/com/ibm/wala/analysis/reflection/java7/MethodHandles.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import com.ibm.wala.util.collections.FilterIterator;
4949
import com.ibm.wala.util.collections.HashMapFactory;
5050
import com.ibm.wala.util.collections.MapIterator;
51+
import com.ibm.wala.util.debug.UnimplementedError;
5152
import com.ibm.wala.util.intset.IntSet;
5253
import com.ibm.wala.util.intset.IntSetUtil;
5354
import com.ibm.wala.util.intset.MutableIntSet;
@@ -301,7 +302,17 @@ public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass rec
301302
.getClassHierarchy()
302303
.lookupClass(TypeReference.JavaLangInvokeMethodHandle),
303304
false,
304-
false);
305+
false) {
306+
@Override
307+
public IR makeIR(Context context, SSAOptions options) throws UnimplementedError {
308+
// MS: On JDK 17, sometimes makeIR() is getting called, and the default
309+
// implementation fails with an error. I don't fully understand the invariants of
310+
// this class, but overriding and returning null makes the tests pass.
311+
// Eventually, we should document this class and figure out if this is the right
312+
// fix.
313+
return null;
314+
}
315+
};
305316
impls.put(target, invokeExactTrampoline);
306317
}
307318

core/src/main/java/com/ibm/wala/classLoader/SyntheticMethod.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ public SSAInstruction[] getStatements(@SuppressWarnings("unused") SSAOptions opt
269269
* @param options options governing IR conversion
270270
*/
271271
public IR makeIR(Context context, SSAOptions options) throws UnimplementedError {
272-
throw new UnimplementedError("haven't implemented IR yet for class " + getClass());
272+
throw new UnimplementedError(
273+
"haven't implemented IR yet for class " + getClass() + ", method " + method);
273274
}
274275

275276
@Override

core/src/main/java/com/ibm/wala/ipa/slicer/SlicerUtil.java

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -93,28 +93,13 @@ public static void dumpSliceToFile(Collection<Statement> slice, String fileName)
9393
}
9494
}
9595

96-
public static int countAllocations(Collection<Statement> slice) {
96+
public static int countAllocations(Collection<Statement> slice, boolean applicationOnly) {
9797
int count = 0;
9898
for (Statement s : slice) {
9999
if (s.getKind().equals(Statement.Kind.NORMAL)) {
100100
NormalStatement ns = (NormalStatement) s;
101101
if (ns.getInstruction() instanceof SSANewInstruction) {
102-
count++;
103-
}
104-
}
105-
}
106-
return count;
107-
}
108-
109-
public static int countApplicationAllocations(Collection<Statement> slice) {
110-
int count = 0;
111-
for (Statement s : slice) {
112-
if (s.getKind().equals(Statement.Kind.NORMAL)) {
113-
NormalStatement ns = (NormalStatement) s;
114-
if (ns.getInstruction() instanceof SSANewInstruction) {
115-
AnalysisScope scope = s.getNode().getClassHierarchy().getScope();
116-
if (scope.isApplicationLoader(
117-
s.getNode().getMethod().getDeclaringClass().getClassLoader())) {
102+
if (!applicationOnly || fromApplicationLoader(s)) {
118103
count++;
119104
}
120105
}
@@ -123,13 +108,22 @@ public static int countApplicationAllocations(Collection<Statement> slice) {
123108
return count;
124109
}
125110

126-
public static int countThrows(Collection<Statement> slice) {
111+
private static boolean fromApplicationLoader(Statement s) {
112+
return s.getNode()
113+
.getClassHierarchy()
114+
.getScope()
115+
.isApplicationLoader(s.getNode().getMethod().getDeclaringClass().getClassLoader());
116+
}
117+
118+
public static int countThrows(Collection<Statement> slice, boolean applicationOnly) {
127119
int count = 0;
128120
for (Statement s : slice) {
129121
if (s.getKind().equals(Statement.Kind.NORMAL)) {
130122
NormalStatement ns = (NormalStatement) s;
131123
if (ns.getInstruction() instanceof SSAAbstractThrowInstruction) {
132-
count++;
124+
if (!applicationOnly || fromApplicationLoader(s)) {
125+
count++;
126+
}
133127
}
134128
}
135129
}
@@ -228,15 +222,17 @@ public static int countReturns(Collection<Statement> slice) {
228222
return count;
229223
}
230224

231-
public static int countGetfields(Collection<Statement> slice) {
225+
public static int countGetfields(Collection<Statement> slice, boolean applicationOnly) {
232226
int count = 0;
233227
for (Statement s : slice) {
234228
if (s.getKind().equals(Statement.Kind.NORMAL)) {
235229
NormalStatement ns = (NormalStatement) s;
236230
if (ns.getInstruction() instanceof SSAGetInstruction) {
237231
SSAGetInstruction p = (SSAGetInstruction) ns.getInstruction();
238232
if (!p.isStatic()) {
239-
count++;
233+
if (!applicationOnly || fromApplicationLoader(s)) {
234+
count++;
235+
}
240236
}
241237
}
242238
}

core/src/test/java/com/ibm/wala/core/tests/slicer/SlicerTest.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ public void testSlice3()
209209
Slicer.computeBackwardSlice(
210210
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
211211
SlicerUtil.dumpSlice(slice);
212-
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice));
212+
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice, false));
213213
}
214214

215215
@Test
@@ -598,7 +598,7 @@ public void testTestId()
598598
Slicer.computeBackwardSlice(
599599
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
600600
SlicerUtil.dumpSlice(slice);
601-
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice));
601+
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice, false));
602602
}
603603

604604
@Test
@@ -626,7 +626,7 @@ public void testTestArrays()
626626
Slicer.computeBackwardSlice(
627627
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
628628
SlicerUtil.dumpSlice(slice);
629-
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice));
629+
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice, false));
630630
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAloads(slice));
631631
}
632632

@@ -655,7 +655,7 @@ public void testTestFields()
655655
Slicer.computeBackwardSlice(
656656
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
657657
SlicerUtil.dumpSlice(slice);
658-
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice));
658+
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice, false));
659659
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countPutfields(slice));
660660
}
661661

@@ -686,7 +686,7 @@ public void testThin1()
686686
Slicer.computeBackwardSlice(
687687
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
688688
SlicerUtil.dumpSlice(slice);
689-
Assert.assertEquals(3, SlicerUtil.countAllocations(slice));
689+
Assert.assertEquals(3, SlicerUtil.countAllocations(slice, false));
690690
Assert.assertEquals(2, SlicerUtil.countPutfields(slice));
691691

692692
// compute thin slice .. ignore base pointers
@@ -699,7 +699,7 @@ public void testThin1()
699699
ControlDependenceOptions.NONE);
700700
slice = computeBackwardSlice;
701701
SlicerUtil.dumpSlice(slice);
702-
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice));
702+
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice, false));
703703
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countPutfields(slice));
704704
}
705705

@@ -728,7 +728,7 @@ public void testTestGlobal()
728728
Slicer.computeBackwardSlice(
729729
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
730730
SlicerUtil.dumpSlice(slice);
731-
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice));
731+
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice, false));
732732
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countPutstatics(slice));
733733
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countGetstatics(slice));
734734
}
@@ -758,7 +758,7 @@ public void testTestMultiTarget()
758758
Slicer.computeBackwardSlice(
759759
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
760760
SlicerUtil.dumpSlice(slice);
761-
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice));
761+
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countAllocations(slice, false));
762762
}
763763

764764
@Test
@@ -787,7 +787,7 @@ public void testTestRecursion()
787787
Slicer.computeBackwardSlice(
788788
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
789789
SlicerUtil.dumpSlice(slice);
790-
Assert.assertEquals(slice.toString(), 3, SlicerUtil.countAllocations(slice));
790+
Assert.assertEquals(slice.toString(), 3, SlicerUtil.countAllocations(slice, false));
791791
Assert.assertEquals(slice.toString(), 2, SlicerUtil.countPutfields(slice));
792792
}
793793

@@ -819,7 +819,7 @@ public void testPrimGetterSetter()
819819
Slicer.computeBackwardSlice(
820820
s, pcg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.FULL);
821821
SlicerUtil.dumpSlice(slice);
822-
Assert.assertEquals(slice.toString(), 0, SlicerUtil.countAllocations(slice));
822+
Assert.assertEquals(slice.toString(), 0, SlicerUtil.countAllocations(slice, false));
823823
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countPutfields(slice));
824824
}
825825

@@ -878,7 +878,7 @@ public void testPrimGetterSetter2()
878878
Slicer.computeBackwardSlice(
879879
s, pcg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
880880
SlicerUtil.dumpSlice(slice);
881-
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice));
881+
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countAllocations(slice, false));
882882
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countPutfields(slice));
883883
}
884884

@@ -906,10 +906,9 @@ public void testTestThrowCatch()
906906
Collection<Statement> slice =
907907
Slicer.computeBackwardSlice(
908908
s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.NONE);
909-
SlicerUtil.dumpSlice(slice);
910-
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countApplicationAllocations(slice));
911-
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countThrows(slice));
912-
Assert.assertEquals(slice.toString(), 1, SlicerUtil.countGetfields(slice));
909+
Assert.assertEquals("wrong number of allocations", 1, SlicerUtil.countAllocations(slice, true));
910+
Assert.assertEquals("wrong number of throws", 1, SlicerUtil.countThrows(slice, true));
911+
Assert.assertEquals("wrong number of getfields", 1, SlicerUtil.countGetfields(slice, true));
913912
}
914913

915914
@Test

shrike/src/main/java/com/ibm/wala/shrike/shrikeCT/ClassReader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ private void parse() throws InvalidClassFileException {
6767
if (magic != MAGIC) {
6868
throw new InvalidClassFileException(offset, "bad magic number: " + magic);
6969
}
70-
if (majorVersion < 45 || majorVersion > 60) {
70+
// Support class files up through JDK 17 (version 61)
71+
if (majorVersion < 45 || majorVersion > 61) {
7172
throw new InvalidClassFileException(
7273
offset, "unknown class file version: " + majorVersion + '.' + minorVersion);
7374
}

util/.settings/org.eclipse.jdt.core.prefs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
2323
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
2424
org.eclipse.jdt.core.compiler.problem.comparingIdentical=error
2525
org.eclipse.jdt.core.compiler.problem.deadCode=warning
26-
org.eclipse.jdt.core.compiler.problem.deprecation=error
26+
org.eclipse.jdt.core.compiler.problem.deprecation=disabled
2727
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
2828
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
2929
org.eclipse.jdt.core.compiler.problem.discouragedReference=error

0 commit comments

Comments
 (0)