NullPointerException from Label.isSameSubroutine()
Under certain circumstances it is possible to have a NullPointerException from
Label.isSameSubroutine() while computing the basic blocks in
MethodWriter.visitMaxes(). The immediate problem is that the field
srcAndRefPositions of the argument block will be null. This seems to happen
when the label preceeds a JSR instruction (sometimes by a few instructions,
that is, the label need not be immediately before the JSR) and that label has
no forward references.
Seems to me this can be fixed by better management of the srcAndRefPositions
field in Label. I have hacked inSameSubroutine() thusly
boolean inSameSubroutine(final Label block) {
// BEGIN: MY CHANGE
if (block.srcAndRefPositions == null) {
block.srcAndRefPositions = new int[srcAndRefPositions.length];
}
// END: MY CHANGE
for (int i = 0; i < srcAndRefPositions.length; ++i) {
if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
return true;
}
}
return false;
}
with no ill effects, but probably there is a better way to fix it.
This comes up because my transformation has to remap labels occasionally, so
sometimes the generated code has two labels on the same code position, and the
second label is never actually referenced. (This happens because the I cannot
know whether the new label is truly needed until after the labels need to be
created.)
I have been able to fix this problem in my code by having it insert a GOTO to
the second label immediately before the second label, thus insuring that the
label has a forward reference. That is, instead of generating
...
OP1
L1:
L2:
OP2
...
I now generate
...
OP1
L1:
GOTO L2
L2:
OP2
...
This results in silly looking bytecode, but it keeps the control-flow algorithm
in Label happy.