mirror of https://github.com/sbt/sbt.git
fix: Fix NoClassDefFoundError after changing val in build.sbt (#8521)
**Problem** When a val definition in build.sbt changes and the user runs `reload`, sbt crashes with `NoClassDefFoundError: $Wrap<hash>$`. ``` java.lang.NoClassDefFoundError: $Wrape8743d4f36$ at $Wrap0b8ea34d40$.$anonfun$1(build.sbt:1) ``` The workaround was to delete `project/target` directory. **Solution** The root cause was that imports were not included in the hash calculation when evaluating build.sbt expressions. When a val definition changes: 1. Its `$Wrap` module gets a new hash 2. Settings that reference the val get new imports pointing to the new module 3. But if the setting expression didn't change, its hash was the same 4. The old cached class was loaded with bytecode referencing the old module Fix: Include imports in the hash calculation in `Eval.evalCommon`. Also re-enable `cleanEvalClasses` in `Load.scala` which was disabled pending this fix.
This commit is contained in:
parent
dc0d055069
commit
727f4b05c6
|
|
@ -216,6 +216,10 @@ class Eval(
|
|||
digester.update(bytes(ev.extraHash))
|
||||
// Include SNAPSHOT classpath hash to invalidate cache when sbt version changes (fixes #7713)
|
||||
digester.update(bytes(snapshotClasspathHash))
|
||||
// Include imports in hash to invalidate cache when definition module names change (fixes #7424)
|
||||
imports.strings.foreach { imp =>
|
||||
digester.update(bytes(imp))
|
||||
}
|
||||
val d = digester.digest()
|
||||
val hash = Hash.toHex(d)
|
||||
val moduleName = makeModuleName(hash)
|
||||
|
|
|
|||
|
|
@ -866,11 +866,9 @@ private[sbt] object Load {
|
|||
)
|
||||
}
|
||||
val loadedProjects = processAutoAggregate(loadedProjects0, uri)
|
||||
// TODO: Uncomment when we fixed https://github.com/sbt/sbt/issues/7424
|
||||
// likely keepClassFiles isn't covering enough.
|
||||
// timed("Load.loadUnit: cleanEvalClasses", log) {
|
||||
// cleanEvalClasses(defDir, keepClassFiles)
|
||||
// }
|
||||
timed("Load.loadUnit: cleanEvalClasses", log) {
|
||||
cleanEvalClasses(defDir, keepClassFiles)
|
||||
}
|
||||
val defs = if (defsScala.isEmpty) defaultBuildIfNone :: Nil else defsScala
|
||||
// HERE we pull out the defined vals from memoSettings and unify them all so
|
||||
// we can use them later.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
val myVersion = "1.0.0"
|
||||
name := myVersion
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
val myVersion = "2.0.0"
|
||||
name := myVersion
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# https://github.com/sbt/sbt/issues/7424
|
||||
> name
|
||||
$ copy-file changes/build.sbt build.sbt
|
||||
> reload
|
||||
> name
|
||||
Loading…
Reference in New Issue