google / error-prone

Catch common Java mistakes as compile-time errors

Home Page:https://errorprone.info

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

False alarm from ClassInitializationDeadlock for inner enum implementing outer interface with default method

PhilippWendler opened this issue · comments

Error Prone 2.27.0 produces a ClassInitializationDeadlock warning for the following code:

public interface TestInterface {

  default Object foo() {
    return null;
  }

  public enum TestEnum implements TestInterface {
    INSTANCE;
  }
}

The exact message is

TestInterface.java:8: warning: [ClassInitializationDeadlock] Possible class initialization deadlock: TestEnum is a subclass of the containing class TestInterface
    INSTANCE;
    ^
    (see https://errorprone.info/bugpattern/ClassInitializationDeadlock)

Interestingly, it does not happen with a class instead of an enum, nor if I remove the default method.

My assumption is that this is a false alarm, because I don't see how initializing TestInterface would require initializing TestEnum.

Thanks, this is a bug, it should be handling enums as well as classes here, instead of scanning the member enum's fields:

if (member.getKind().equals(Tree.Kind.CLASS)) {
continue;

If there was a field declared directly in TestInterface (instead of nested instead the enum) that could deadlock:

public interface TestInterface {

  default Object foo() {
    return null;
  }

  static final TestInterface FOO = TestEnum.INSTANCE; // possible deadlock

  public enum TestEnum implements TestInterface {
    INSTANCE;
  }
}

It is only reported if the interface has a default method, because interfaces with default methods can participate in class initialization cycles due to the bit about interfaces with 'non-abstract, non-static methods' in JVMS 5.5

Having the same issue. It so far has broken our builds on every project internal and my open source projects.

@cushon assuming this is fixed for the enum implements interface problem will it still report if you have an interface with default methods and/or static final fields even if those fields and/or methods are not used by the enum?

I assume it is just with cycles but given this bug I'm not sure I understand how this check works.

it will continue to report cases where there's a cyclic dependency between class initializers, including cycles that involve interfaces with default methods and enums.

I pushed a 2.27.1 release with a fix for this.