Skip to content
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

NPE inspection false positive with lazy getters #440

Closed
SOF3 opened this issue Jan 18, 2018 · 0 comments · Fixed by #692
Closed

NPE inspection false positive with lazy getters #440

SOF3 opened this issue Jan 18, 2018 · 0 comments · Fixed by #692

Comments

@SOF3
Copy link

SOF3 commented Jan 18, 2018

Short description

(Skip to the "Sample code" section; nobody wants to read this complicated "short" description)
When a lazy getter field is initialized by an expression that references a constructor-initialized final field, a ConstantConditions inspection ("dereference of *** may produce NPE") is triggered. Had the field not been a lazy getter, this would indeed have been possible, but since lazy getters can only be possibly called after initialization (it would have been unreasonable to make it a lazy getter if it is called immediately), such NPE is not practically possible.

Expected behavior

The plugin should stop the IDE from identifying the lazy initializer expression as something executed before constructor call.

Version information

  • IDEA Version: IntelliJ IDEA 173.4528.2 (2017.3.4 EAP Ultimate)
  • JDK Version: JRE 1.8.0_152-release-1024-b11 amd64; JVM OpenJDK 64-bit Server VM by JetBrains
  • OS Type & Version: Windows 10 Pro
  • Lombok Plugin Version: 0.15.17.2
  • Lombok Dependency Version: org.projectlombok:lombok:1.16.20

Sample code

Consider this example class:

class Foo{
	private Bar bar;
	@lombok.Getter(lazy = true) private final String barString = bar.toString();

	public Foo(Bar bar){
		this.bar = bar;
	}
}

The Bar class is an empty class.

The decompiled .class becomes this:

class Foo {
    private Bar bar;
    private final AtomicReference<Object> barString = new AtomicReference();

    public Foo(Bar bar) {
        this.bar = bar;
    }

    public String getBarString() {
        Object value = this.barString.get();
        if (value == null) {
            AtomicReference var2 = this.barString;
            synchronized(this.barString) {
                value = this.barString.get();
                if (value == null) {
                    String actualValue = this.bar.toString();
                    value = actualValue == null ? this.barString : actualValue;
                    this.barString.set(value);
                }
            }
        }

        return (String)((String)(value == this.barString ? null : value));
    }
}

To be sure, I made IDEA inspect the decompiled code, and it indeed triggers no inspection with the decompiled code. On the other hand, I get this with the original code:

image

Other information

If you fail to reproduce the problem and want more information, please provide a private means of communication. I don't want to disclose my project details to the public.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants