question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Do not crash in backend when method is too large

See original GitHub issue

When I use Mirror of scala 3 to generate a typeclass list, the exception occurs. I know it’s the hard limit of jvm of method size, but how can I circumvent this issue.

ps: When delete some fields of Data class it works, but any other solution?

Compiler version

sbt: 1.6.0

scala: 3.1.0

Minimized example

import scala.compiletime.*
import scala.deriving.Mirror

object Main extends App {

  trait FromString[A] {
    def convert(str: String): A
  }
  object FromString {
    given FromString[Int] = (str) => str.toInt
    given FromString[Double] = (str) => str.toDouble
    given FromString[String] = (str) => str
  }

  inline def getTypeclassInstances[F[_], A <: Tuple]: List[F[Any]] =
    inline erasedValue[A] match {
      case _: EmptyTuple => Nil
      case _: (head *: tail) =>
        val headTypeClass =
          summonInline[F[head]]
        val tailTypeClasses =
          getTypeclassInstances[F, tail]
        headTypeClass.asInstanceOf[F[Any]] :: getTypeclassInstances[F, tail]
    }

  inline def summonInstancesHelper[F[_], A](using
      m: Mirror.Of[A]
  ): List[F[Any]] =
    getTypeclassInstances[F, m.MirroredElemTypes]

  case class Data(
      ip: String,
      method: String,
      uri: String,
      protocal: String,
      httpStatus: Int,
      byteSent: Double,
      reqLength: Double,
      reqTime: Double,
      respTime: Double,
      referer: String,
      device: String
  )

  val types =
    summonInstancesHelper[FromString, Data]
  println(types.mkString("\r\n"))
}

Output

[error] scala.tools.asm.MethodTooLargeException: Method too large: parse/Main$.<clinit> ()V
[error] scala.tools.asm.MethodWriter.computeMethodInfoSize(MethodWriter.java:2087)
[error] scala.tools.asm.ClassWriter.toByteArray(ClassWriter.java:489)
[error] dotty.tools.backend.jvm.GenBCodePipeline$Worker2.getByteArray$1(GenBCode.scala:478)
[error] dotty.tools.backend.jvm.GenBCodePipeline$Worker2.addToQ3(GenBCode.scala:484)
[error] dotty.tools.backend.jvm.GenBCodePipeline$Worker2.run(GenBCode.scala:461)
[error] dotty.tools.backend.jvm.GenBCodePipeline.buildAndSendToDisk(GenBCode.scala:562)
[error] dotty.tools.backend.jvm.GenBCodePipeline.run(GenBCode.scala:525)
[error] dotty.tools.backend.jvm.GenBCode.run(GenBCode.scala:63)
[error] dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:308)
[error] scala.collection.immutable.List.map(List.scala:246)
[error] dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:309)
[error] dotty.tools.backend.jvm.GenBCode.runOn(GenBCode.scala:71)
[error] dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:261)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
[error] dotty.tools.dotc.Run.runPhases$5(Run.scala:272)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:280)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
[error] dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:68)
[error] dotty.tools.dotc.Run.compileUnits(Run.scala:289)
[error] dotty.tools.dotc.Run.compileSources(Run.scala:222)
[error] dotty.tools.dotc.Run.compile(Run.scala:206)
[error] dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
[error] dotty.tools.xsbt.CompilerBridgeDriver.run(CompilerBridgeDriver.java:88)
[error] dotty.tools.xsbt.CompilerBridge.run(CompilerBridge.java:22)
[error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:91)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:192)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:247)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:182)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:163)
[error] sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:239)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:163)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:210)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5(Incremental.scala:177)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5$adapted(Incremental.scala:175)
[error] sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:461)
[error] sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:116)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52)
[error] sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:263)
[error] sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:416)
[error] sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:503)
[error] sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:403)
[error] sbt.internal.inc.Incremental$.apply(Incremental.scala:169)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:482)
[error] sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:420)
[error] sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137)
[error] sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:2366)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$2(Defaults.scala:2316)
[error] sbt.internal.server.BspCompileTask$.$anonfun$compute$1(BspCompileTask.scala:30)
[error] sbt.internal.io.Retry$.apply(Retry.scala:46)
[error] sbt.internal.io.Retry$.apply(Retry.scala:28)
[error] sbt.internal.io.Retry$.apply(Retry.scala:23)
[error] sbt.internal.server.BspCompileTask$.compute(BspCompileTask.scala:30)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:2314)
[error] scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] sbt.Execute.work(Execute.scala:291)
[error] sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] java.lang.Thread.run(Thread.java:748)
[error]
[error] stack trace is suppressed; run last Compile / compileIncremental for the full output
[error] (Compile / compileIncremental) scala.tools.asm.MethodTooLargeException: Method too large: parse/Main$.<clinit> ()V
[error] Total time: 2 s, completed 2022-1-5 14:11:19

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
devlaamcommented, Mar 9, 2022

I have found a related example (below, minimised from a real word application) that results in an “java.lang.OutOfMemoryError: Java heap space” on a 24GB heap. Only a slight modification results in an “MethodTooLargeException”. So probably there is more going on behind the scenes. Previously discussed on the Scala Users Forum.

/**  Compile with:
sbt.version=1.6.2
scalaVersion := "3.1.1"
scalacOptions ++= Seq("-feature","-deprecation","-unchecked","-explain"),
libraryDependencies ++= Seq("com.softwaremill.quicklens" %% "quicklens" % "1.8.3")                                   
*/

package HeapError

import com.softwaremill.quicklens._

/* Presence of AnyVal turns 'MethodTooLargeException' into an 
   'java.lang.OutOfMemoryError: Java heap space' error */
class Moment(val value: Long) extends AnyVal with Ordered[Moment]
{ def compare(that: Moment) = (this.value - that.value).sign.toInt
  def isZero = value == 0 }
  
case class Timers(
  wakeTime:            Moment, 
  constructionTime:    Moment, 
  initializationTime:  Moment, 
  activationTime:      Moment, 
  clock:               Moment, 
  lastSignal:          Moment, 
  lastTransmission:    Moment, 
  lastHeartbeat:       Moment, 
  lastClockSet:        Moment, 
  lastFail:            Moment) 

case class Counters(
  missedAcks:   Int, 
  upSinceHB:    Int, 
  downSinceHB:  Int, 
  failSinceHB:  Int, 
  upSum:        Int, 
  downSum:      Int, 
  failSum:      Int) 

case class SystemState(
  mcuTemperature: Double, 
  batteryCharge:  Double, 
  bufferSpace:    Double, 
  health:         Double)
 
case class Monitor(timers: Timers, counters: Counters, systemState: SystemState) 
{ def setClockInit(time: Moment): Monitor = this
    .modifyAll(_.timers.clock, 
               _.timers.initializationTime,  
               _.timers.lastClockSet, 
               _.timers.lastSignal, 
               _.timers.lastTransmission)
    .setToIf(!time.isZero)(time) }
1reaction
bishaboshacommented, Jan 5, 2022

I say we could reopen this to give a better error message to the user, rather than crash

Read more comments on GitHub >

github_iconTop Results From Across the Web

Scala 3 Method Too large when using Mirror - Stack Overflow
When I use Mirror of scala 3 to generate a typeclass list, the exception occurs. I know it's the hard limit of jvm...
Read more >
java.lang.RuntimeException: Method code too large!
I am working on a scala-internal DSL that "serialize" its data structures into scala code that get's interpreted back from files to generate...
Read more >
Let It Crash: Best Practices for Handling Node.js Errors on ...
We recommend running more than one process and to use a load balancer to handle the scheduling.
Read more >
Method code too large - #58 by duyluong - Katalon Studio
Im experiencing this and I dont have 500 lines…more like 400, which is really not alot, especially when you write test by hand...
Read more >
Top 10 Most Common Node.js Developer Mistakes - Toptal
Invoking this “sortUsersByAge” function may be fine if run on a small “users” array, but with a large array, it will have a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found