-
Notifications
You must be signed in to change notification settings - Fork 306
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
Use of += on a private String in a nested class causes IllegalStateException when imported #1146
Comments
Thanks for reporting this issue in such great detail! I had a quick look and can reproduce it thanks to your demo repository – which highly appreciated. 💚 |
I had a look at it and I think the Stringbuilder is not the problem, at least not directly. To me it seems that the synthetic access is not registered correctly or cannot be resolved. Right now I do not fully understand it, but will investigate further :) |
FYI: |
We weren't aware that the compiler occasionally generates synthetic `access$123` methods that call constructors. More precisely for the following constellation ``` class Outer { String field = ""; class Inner { void concat() { field += "any"; } } } ``` the compiler generates bytecode instantiating and using a `StringBuilder`. But for constructor calls the synthetic access resolution was not hooked in, because we assumed that those methods would never call a constructor. This in turn lead to the bug ``` java.lang.IllegalStateException: Never found a JavaCodeUnit that matches supposed origin CodeUnit{name='access$123'... ``` I.e. the method `access$123` was filtered out as synthetic, but the origin of the constructor call had not been resolved to the actual `Inner.concat` method. Resolves: #1146 Resolves: #1194
JDK version: Amazon Corretto 11.0.16
Java Source/Target version: 8
ArchUnit version: 1.0.1
At least this version of the JDK, when targeting Java 8, replaces uses of += with StringBuilder in a way that results in a synthetic access method being created that ArchUnit doesn't seem to know what to do with.
Here's a class, that when imported, that triggers the error in ArchUnit
The following test will fail with the below error
java.lang.IllegalStateException: Never found a JavaCodeUnit that matches supposed origin CodeUnit{name='access$084', descriptor=(LOuter;Ljava/lang/Object;)Ljava/lang/String;, declaringClassName='Outer'}
Full Stack Trace:
This implementation will pass the test
Debugging into ArchUnit, I saw that the
RawAccessRecord
containing theCodeUnit
mentioned in the error had a target that mentionedStringBuilder
, which isn't anywhere in the original code. However, if you look at the bytecode, the compiler has decided to replace the use of+=
and use aStringBuilder
instead. According to the Java Language Spec, this is allowed.This is a bytecode disassembly showing use of StringBuilder

A complete repro is available at https://github.com/OneGeek/archunit-bug-repro/ , which includes tests that import classes implemented with and without the use of
+=
. Only the one without passes.The text was updated successfully, but these errors were encountered: