2015-12-03 294 views
1

我有一个简单的测试程序来尝试...内存泄漏

object ActorLeak extends App { 
    val system = ActorSystem("ActorLeak") 
    val times = 100000000 
    for (i <- 1 to times) { 
    val myActor = system.actorOf(Props(classOf[TryActor], i), name = s"TryActor-$i") 
    //Thread sleep 100 
    myActor ! StopCmd 
    if (i % 10000 == 0) 
     println(s"Completed $i") 
    } 
    println(s"Creating and stopping $times end.") 
    val hookThread = new Thread(new Runnable { 
    def run() { 
     system.shutdown() 
    } 
    }) 
    Runtime.getRuntime.addShutdownHook(hookThread) 
} 
case object StopCmd 
class TryActor(no: Int) extends Actor { 
    def receive = { 
    case StopCmd => context stop self 
    } 
} 

我发现:一段时间的OutOfMemoryError,有时会使JVM死了,跑慢点慢点......

是否有记忆泄漏创建/停止演员?

+0

我把你的for循环重写为一个递归函数,认为它可能是咀嚼内存的'1 to times'范围的分配;但是我仍然看到随着时间的推移内存使用量的显着增长(类似于您的结果)。 –

回答

4

演员创建和消息传递都是异步的,当actorOf返回时,这并不意味着演员已创建,并且当!返回时,并不表示演员已收到消息或对消息采取行动。

这意味着你实际上并不是为每次迭代创建和停止一个actor,而是触发创建并发送一条消息,这个循环在排队创建actor时可能比消息到达并触发stop的消息填满了你的JVM堆。

要做你认为你正在尝试做的事情,你必须在接收到StopCmd后提供演员的回应,然后等待循环内部再继续下一次迭代。这可以通过ask模式连同Await.result来阻止主线程,直到参与者回复已经返回。

请注意,这仅用于您的理解,而不是您在使用Akka的实际系统中所做的操作。