I have the following Comparator
implemenation:
private static final class ValueComparator<Value_, Point_ extends Comparable<Point_>> implements Comparator<Value_> {
private final Function<Value_, Point_> indexFunction;
public ValueComparator(Function<Value_, Point_> indexFunction) {
this.indexFunction = Objects.requireNonNull(indexFunction);
}
@Override
public int compare(Value_ o1, Value_ o2) {
if (o1 == o2) {
return 0;
}
Point_ point1 = indexFunction.apply(o1);
Point_ point2 = indexFunction.apply(o2);
if (point1 == point2) {
return 0;
}
int comparison = point1.compareTo(point2);
if (comparison != 0) {
return comparison;
}
// Identity Hashcode for duplicate protection; we must always include duplicates.
// Ex: two different games on the same time slot
int identityHashCode1 = System.identityHashCode(o1);
int identityHashCode2 = System.identityHashCode(o2);
return Integer.compare(identityHashCode1, identityHashCode2);
}
}
This code runs for a while, and then suddenly throws an NPE - indexFunction
somehow becomes null
, even though it was checked to be non-null in the constructor.
Obviously, this was bugging me, so I went looking, and I found that the indexFunction
is Math::abs
, a reference to a static method. And java.lang.Math.abs(int)
is @HotSpotIntrinsicCandidate
.
Does that mean that HotSpot has, at some point, intrinsified the method and therefore the method reference became invalid? How do I protect myself against this sort of thing?
$ java -version
openjdk version "11.0.12" 2021-07-20
OpenJDK Runtime Environment Temurin-11.0.12+7 (build 11.0.12+7)
OpenJDK 64-Bit Server VM Temurin-11.0.12+7 (build 11.0.12+7, mixed mode)
Turns out the answer is much simpler and much less sensational.
The argument to the indexFunction
was null, and with the function expecting int
, the NPE came from unboxing. In this case, the NPE still points to the indexFunction
, as opposed to some code inside of it, which initially led me down a totally wrong path.
Apparently I wasn't as thorough in checking my inputs as I had thought. Rookie mistake, case closed.