New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crash during compilation on JDK 8 when using JSpecify 0.3.0-alpha-1 #302
Comments
FWIW a possible difference between this and previous test cases is that the code being compiled uses |
After further thought I realized we probably want to have NullAway support JDK 8 for some time longer, to support more open-source projects that haven't updated. So having JSpecify support building with JDK 8 would be helpful to us. |
Thanks very much for testing this and for the repro instructions. This is new: We'd known that building with Java 8 could produce a warning (which becomes an error under Brain dump follows. Testing notesIt does appear that the code compiles fine if the usages of (I would say "And the code compiles fine with the 0.2.0 release," but: In order to test with 0.2.0, I have to change the test code such that... the usages of One annotation of either type on a method is enough to produce the error. That's true even if the annotation is redundant on account of a matching annotation on the enclosing class. Removing It also appears that the code compiles fine if I build with JDK11 but with Finally, it appears that NullAway is not necessary for the crash: A build of your Why this is happeningPart of the story here is almost certainly #245: We used to have the It's still a bit of a mystery as to why this error appears only with certain test code. [edit: I believe msridhar suggested that it has something to do with which cases javac needs to ask "Is this a type-use annotation, an annotation applicable to this element, or both?] But it's not surprising in general that a "missing" internal class could cause problems for javac, and it's not surprising that that could cause crashes that appear and disappear for mysterious reasons. How to avoid itIn an ideal world, everyone would build with a newer JDK, even if they target Java 8, typically by using A theoretical way for a project to continue to be able to build with javac8 to use a Another spin on that possibility is for the main A different approach is to omit This continues to need more thoughtYuck. But thanks again. |
Oh, this is a good place to recall that |
Thanks so much for investigating, @cpovirk. I have one question. Based on the stack trace and error message, I don't think this crash in JDK 8 javac is intended behavior. Also it looks like one can at least still backport fixes to JDK 8 for future patch releases. Here is the line of code throwing the assertion error: I wonder if we could submit a PR that changes this assertion to something less crash-y? Like maybe emit another warning instead for an unknown enum constant? Then at least this issue could be fixed in a future JDK 8 release, which gives us more options (like leaving things the way they are and telling users to update their JDK 8 release). Of course this doesn't help with working around the current crash. It looks like someone submitted an issue on this before: https://bugs.openjdk.org/browse/JDK-8279557 They didn't have a reproducer so it got closed, but we have one now. If we think it's worthwhile, I can try to re-open that issue or submit a new one, to see if we get feedback on the possibility of a change. Let me know if we think that's worth a try. |
Thank you! That is a better thought than any of the thoughts in my post :) It does seem likely that upstream would like the compiler to not crash, regardless of how strange the code we feed it is. It's possible that they could respond by changing the crash into a more normal but still fatal error, or it's possible that they don't deem this fix worth backporting. But maybe they'll see the value in making it easier for libraries to use the Reproducing does look easy. If you're up for taking things to upstream, that would be terrific. $ tail -n +1 *.java
==> A.java <==
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.MODULE;
import java.lang.annotation.Target;
@Target({METHOD, MODULE})
@interface A {}
==> B.java <==
class B {
@A void b() {}
}
|
I will report this upstream and then report back. Let's hope for a positive response :-) |
The bug report got created: https://bugs.openjdk.org/browse/JDK-8295314 However, it got erroneously closed as "Cannot reproduce" because the repro instructions were not followed correctly (JDK 17 was used to compile I will try to use a link they provided to "submit additional info" to clarify. But @cpovirk @kevinb9n if we know someone with a JDK bug system account who could comment directly, that might be more effective. |
Thanks. I think @eamonnmcmanus said that he had The Power? Éamonn, are you up for it? |
I do indeed have an openjdk.org account. Let me know if "submit additional info" doesn't produce the desired results and I can comment on the bug. |
Update: it looks like "submit additional info" worked as the bug has been re-opened. Not sure who would look at this / prioritize it. I'll wait a bit and see what happens. |
For those familiar with the JDK bug reporting process: is there any way to know if JDK-8295314 has or will be triaged? I am wondering how we can get the right eyes on it. I think we have a good case that it's worth fixing, but probably we need someone involved with JDK 8 maintenance to see it for it to get noticed, and I'm not sure if that will happen automatically. We're about to add a one-off |
Update: thanks to help from @cushon and @cpovirk, we discovered this bug still exists in the latest version of https://bugs.openjdk.org/browse/JDK-8296010 Our hope is that the new bug gets fixed in the latest Java version, and that eventually we can backport the fix all the way to JDK 8. |
Trying to summarize where we are, which we discussed some in today's meeting:
|
I really like this as a temporary workaround! It's probably the least disruptive option for those who still need to build using JDK8. I just used it to unblock uber/NullAway#673 and get the build green on JDK 8 there. And Error Prone's javac9 is battle tested and reliable. Hopefully in the medium term, we will get a fix backported to JDK 8 so even this workaround is not needed. And then the only remaining issue is not being able to compile with |
This oughtta be mediocre enough to snipe you into editing it: |
The artifact now contains `@NullMarked` and `@NullUnmarked` annotations, so we do not need to create our own copies for testing. We leverage the Error Prone javac to keep builds working on JDK 8; this is a workaround for jspecify/jspecify#302
It looks like the MODULE target can also cause problems with javadoc: https://github.com/wala/WALA/actions/runs/3634061250/jobs/6131766621#step:5:253 I see #351 actually removed |
Oh, thanks for that report. It would be nice if we had a workaround like you describe, but I'm not excited about trying to figure one out right now... :) As it happens, I did release 0.3.0-alpha-3 (because I missed a problem with our module-info). And while I forgot to mention it in the initial release notes, it does additionally contain the change you're looking for. I eventually noticed that and updated https://github.com/jspecify/jspecify/releases/tag/v0.3.0-alpha-3 to mention it. |
Thanks a lot @cpovirk I think the alpha 3 release should fix it! |
Seen in the wild: https://stackoverflow.com/a/76254522/28465 I will continue feeling bad about this and eventually do something about it. |
If we ever get any further info, I'd be curious to know the use case for writing |
Hello, everyone. Just stumbled upon this issue myself. Migrating my codebase away from JSR305 to jspecify and see that compiler raises a warning. Not sure if that was discussed earlier, but have you considered using JDK 9 multi-release jars support? https://openjdk.org/jeps/238 TL;DR you can ship two versions of a class in a single jar. One for everything before Java 9 and then for every release of Java you can have it's own class file. Essentially, for every release of jspecify you can ship two classfiles
Should mitigate the warning under Java 8 target and still support newer targets (even beyond Java 9). |
Sorry, I lost track of this thread... among others recently... :( We had tried a multi-release jar for this purpose a couple years ago, and it turns out that it doesn't achieve that purpose. The idea of a multi-release jar is that the API of the classes is supposed to match across versions. The definition of "API" was left a little fuzzy AFAICT, but the idea seems to (mostly?) be that a compiler should be able to look at whichever version it wants. That means that we can't count on it to look at the version that contains Or maybe the tools are buggy. Even if so, we probably don't want to take an approach that will cause problems for those tools in order to work around a problem with a tool (javac) that is probably at least easier to migrate off of (by upgrading to javac 9+, even while still targeting older versions of Java). |
(But thank you for raising that suggestion! I wish that it had worked out....) |
NullAway branch is here:
https://github.com/uber/NullAway/tree/update-jspecify
This is the crash (see here), which comes when running
./gradlew :test-java-lib:compileJava
on a JDK 8 JVM:From #34 I can't tell if this was intended or not. Do we not support using JSpecify annotations when building on JDK 8? Building on JDK 8 is not a requirement for NullAway (we're planning to remove JDK 8 support soon); I am just wondering if this was intentional.
The text was updated successfully, but these errors were encountered: