spotless icon indicating copy to clipboard operation
spotless copied to clipboard

Non deterministic behavior with exceptions.

Open N3cr0s1s opened this issue 2 years ago • 2 comments

Summary of problem

We have a big java project in which we use spotless, but sometimes we get a "ClassNotFound" exception on buildRelase task. The not found class and when it happens is totally random, there is no underlying cause. In 50% of cases it runs successfully, without errors, in the rest it crashes.

Gradle version

  • localhost: 8.3
  • GitLab CI/CD: 7.5
  • another colleague localhost: 8.4

Spotless version

  • 6.20
  • 6.23.3

Operating system and version

  • Windows 10/11
  • Ubuntu 23
  • Ubuntu 22
  • Gitlab CI/CD - Docker image: gradle:7.5.0-jdk18

Fromatting (Eclipse) Config

https://gist.github.com/N3cr0s1s/00bbc1bc6fbbe6da5e29e54a19defe35

Stacktrace

> Task :base-utilities:spotlessJava FAILED
Step 'eclipse jdt formatter' found problem in 'src/test/java/com/horvatha/hash/Base64Encode.java':
null
java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
	at java.base/java.lang.reflect.Method.invoke(Method.java:577)
	at com.diffplug.spotless.extra.java.EclipseJdtFormatterStep.lambda$apply$0(EclipseJdtFormatterStep.java:67)
	at com.diffplug.spotless.FormatterFunc$NeedsFile.apply(FormatterFunc.java:154)
	at com.diffplug.spotless.FormatterStepImpl$Standard.format(FormatterStepImpl.java:82)
	at com.diffplug.spotless.FormatterStep$Strict.format(FormatterStep.java:103)
	at com.diffplug.spotless.Formatter.compute(Formatter.java:246)
	at com.diffplug.spotless.PaddedCell.calculateDirtyState(PaddedCell.java:203)
	at com.diffplug.spotless.PaddedCell.calculateDirtyState(PaddedCell.java:190)
	at com.diffplug.gradle.spotless.SpotlessTaskImpl.processInputFile(SpotlessTaskImpl.java:105)
	at com.diffplug.gradle.spotless.SpotlessTaskImpl.performAction(SpotlessTaskImpl.java:89)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:577)
	<org.gradle.internal.... too many lines>
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NoClassDefFoundError: org/eclipse/jdt/internal/compiler/impl/CharConstant
	at org.eclipse.jdt.internal.compiler.ast.CharLiteral.computeValue(CharLiteral.java:79)
	at org.eclipse.jdt.internal.compiler.ast.CharLiteral.<init>(CharLiteral.java:28)
	at org.eclipse.jdt.internal.compiler.parser.Parser.consumeToken(Parser.java:10430)
	at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:13114)
	at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:13508)
	at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.parseStatements(MethodDeclaration.java:251)
	at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.parseMethods(TypeDeclaration.java:1143)
	at org.eclipse.jdt.core.dom.CompilationUnitResolver.parse(CompilationUnitResolver.java:656)
	at org.eclipse.jdt.core.dom.ASTParser.internalCreateAST(ASTParser.java:1264)
	at org.eclipse.jdt.core.dom.ASTParser.createAST(ASTParser.java:868)
	at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.parseSourceCode(DefaultCodeFormatter.java:317)
	at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.prepareFormattedCode(DefaultCodeFormatter.java:221)
	at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.format(DefaultCodeFormatter.java:185)
	at org.eclipse.jdt.internal.formatter.DefaultCodeFormatter.format(DefaultCodeFormatter.java:167)
	at com.diffplug.spotless.extra.glue.jdt.EclipseJdtFormatterStepImpl.format(EclipseJdtFormatterStepImpl.java:43)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	... 130 more
Caused by: java.lang.ClassNotFoundException: org.eclipse.jdt.internal.compiler.impl.CharConstant
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
	at com.diffplug.spotless.FeatureClassLoader.findClass(FeatureClassLoader.java:79)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 146 more

Same build, different class not found:

Caused by: java.lang.NoClassDefFoundError: org/eclipse/jdt/internal/compiler/parser/Scanner$ScanContextDetector
Caused by: java.lang.ClassNotFoundException: org.eclipse.jdt.internal.compiler.parser.Scanner$ScanContextDetector

N3cr0s1s avatar Dec 07 '23 10:12 N3cr0s1s

Thanks for the bug report.

  • does it happen with just a regular spotlessApply / spotlessCheck, or only with buildRelase
  • This is besides the point, but I wouldn't expect a release task to use Spotless...

nedtwigg avatar Dec 08 '23 00:12 nedtwigg

With just a regular spotlessApply / spotlessCheck we don't get this exception,but not only the buildRelease task produces this error. There is such a task that generates classes from an xsd, and sometimes it also throws an error.

ext.stGeneratePmGraph = { graphPath, dynamicArguments = [], graphDir = '', taskName = 'stGeneratePmGraph' ->
  task "$taskName"( type: JavaExec ) {
    mainClass = 'xxx.xxx.SchemaToolApp'
    classpath = configurations.schemaTool
    args = [
      'CreatePmGraph',
      resourceLocator( graphPath, graphDir ),
      sources
    ] + dynamicArguments
    jvmArgs = []
    finalizedBy 'spotlessJavaApply'
  }
}

In the meantime, we discovered how to reproduce the error, by running 2 gradle tasks in one command, e.g. gradle cleanAll buildRelease

And the release task runs spotless because they are depends on the compile task of the modules. Like this:

// ---------- formatting ----------

spotless {
  java {
    eclipse().configFile( '../../formatting.xml' )
    lineEndings(com.diffplug.spotless.LineEnding.WINDOWS)
  }
}

compileJava.dependsOn {
  if (project.hasProperty('ci')) {
    [] // as a temporary solution, we use a flag so that it does not run in a CI environment
  }
  else {
    tasks.spotlessJavaApply
  }
}

N3cr0s1s avatar Dec 11 '23 05:12 N3cr0s1s