Play Framework (Scala) 中的 ForkJoinTask[] 和 ForkJoinPool$WorkQueue 内存泄漏
Memory leaking with ForkJoinTask[] and ForkJoinPool$WorkQueue in Play Framework (Scala)
我有一个在 Play Framework v2.3.7 中使用 Scala v2.11.4 编写的应用程序。它在服务器上 运行 并且每周崩溃一次,出现异常 OutOfMemoryError:超出 GC 开销限制。我想弄清楚那里出了什么问题。我制作了内存转储并制作了所有使用的直方图 类(我使用 jmap -histo
)。我发现了非常奇怪的结果:
Object Histogram:
num #instances #bytes Class description
--------------------------------------------------------------------------
1: 24023 787570032 scala.concurrent.forkjoin.ForkJoinTask[]
2: 96965 12420368 * MethodKlass
3: 96965 11250824 * ConstMethodKlass
4: 8424 8652552 * ConstantPoolKlass
5: 8424 7547640 * InstanceKlassKlass
6: 61739 5531288 char[]
7: 7527 4799776 * ConstantPoolCacheKlass
8: 24024 4612608 scala.concurrent.forkjoin.ForkJoinPool$WorkQueue
9: 27289 3543672 byte[]
10: 23190 2597280 scala.concurrent.impl.ExecutionContextImpl$DefaultThreadFactory$$anon
11: 63921 2045472 java.util.concurrent.ConcurrentHashMap$HashEntry
12: 3735 1470112 * MethodDataKlass
13: 42877 1029048 scala.collection.immutable.$colon$colon
14: 8834 1023064 java.lang.Class
所以,有很多ForkJoinTask[]
和ForkJoinPool$WorkQueue
的实例。因此,我假设它是我所有异步调用和应用程序线程的队列和任务。而且我也觉得,理论上应该是完成后直接撤掉。
这个问题的可能原因是什么?也许我错误地配置了一个 ExecutionContext?有人以前遇到过这个问题吗?
您使用的是哪个上下文?根据 documentation,你应该使用
play.api.libs.concurrent.Execution.Implicits.defaultContext
而不是默认值
scala.concurrent.ExecutionContext.Implicits.global
请参阅此 进行解释。
问题已通过使用最新版本的 "scala-reflect" 库(2.11.6 之后的版本)得到解决:
val scalaV = "2.11.6"
scalaVersion := scalaV
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaV
)
我有一个在 Play Framework v2.3.7 中使用 Scala v2.11.4 编写的应用程序。它在服务器上 运行 并且每周崩溃一次,出现异常 OutOfMemoryError:超出 GC 开销限制。我想弄清楚那里出了什么问题。我制作了内存转储并制作了所有使用的直方图 类(我使用 jmap -histo
)。我发现了非常奇怪的结果:
Object Histogram:
num #instances #bytes Class description
--------------------------------------------------------------------------
1: 24023 787570032 scala.concurrent.forkjoin.ForkJoinTask[]
2: 96965 12420368 * MethodKlass
3: 96965 11250824 * ConstMethodKlass
4: 8424 8652552 * ConstantPoolKlass
5: 8424 7547640 * InstanceKlassKlass
6: 61739 5531288 char[]
7: 7527 4799776 * ConstantPoolCacheKlass
8: 24024 4612608 scala.concurrent.forkjoin.ForkJoinPool$WorkQueue
9: 27289 3543672 byte[]
10: 23190 2597280 scala.concurrent.impl.ExecutionContextImpl$DefaultThreadFactory$$anon
11: 63921 2045472 java.util.concurrent.ConcurrentHashMap$HashEntry
12: 3735 1470112 * MethodDataKlass
13: 42877 1029048 scala.collection.immutable.$colon$colon
14: 8834 1023064 java.lang.Class
所以,有很多ForkJoinTask[]
和ForkJoinPool$WorkQueue
的实例。因此,我假设它是我所有异步调用和应用程序线程的队列和任务。而且我也觉得,理论上应该是完成后直接撤掉。
这个问题的可能原因是什么?也许我错误地配置了一个 ExecutionContext?有人以前遇到过这个问题吗?
您使用的是哪个上下文?根据 documentation,你应该使用
play.api.libs.concurrent.Execution.Implicits.defaultContext
而不是默认值
scala.concurrent.ExecutionContext.Implicits.global
请参阅此
问题已通过使用最新版本的 "scala-reflect" 库(2.11.6 之后的版本)得到解决:
val scalaV = "2.11.6"
scalaVersion := scalaV
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaV
)