Жизненный цикл объекта в замыкании - PullRequest
0 голосов
/ 27 мая 2018

Предположим, что замыкание было выполнено в JVM и создает объект в области действия этого замыкания. Сохраняется ли этот объект в пространстве кучи JVM после выполнения замыкания, пока JVM не завершается?

Один разСитуация в Spark. Я использую приведенный ниже код для создания HBase-соединения в исполнителе:

rdd.foreachPartition(par => {

    # create a connection here.
    val connection = ConnectionFactory.createConnection(conf)

    par.foreach(item => {
        ...
    })

    # close this connection.
    connection.close()
})

Очевидно, что в исполнителе создается соединение.

  • И после того, как эта задача будет выполнена, если я никогда не закрою это соединение, что произойдет?

  • Что, если искра спекуляции убьет эту задачу, покасоединение активно?Будет ли соединение по-прежнему удерживаться JVM?

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Я предполагаю, что это не относится только к Spark, но в целом к ​​JVM.

Прежде всего, переменная, созданная внутри области действия функции, является не чем иным, как локальной переменной.Следовательно, после окончания области действия эта локальная переменная не имеет ссылки и имеет право на сборщик мусора.Таким образом, в вашем конкретном случае, если ваш connection проект не имеет close(), вызываемого должным образом (из-за, возможно, некоторого исключения, возникающего между ними), объект connection собирается GC, но само соединение незакрыто.Мы называем эту ситуацию утечкой соединения.

Один из лучших методов решения этой проблемы - обеспечить закрытие каждого соединения, на try...finally, что в Java8 имеет метод try-with-resource для быстрого вызова.Для Scala можно создать эквивалентную структуру, см. этот пост для получения более подробной информации / извлеченного урока.

Для вашего последнего вопроса,

Что если искраспекуляция убивает эту задачу, пока соединение активно?Будет ли соединение по-прежнему удерживаться JVM?

JVM должным образом не будет больше удерживать соединение.И когда одноранговое соединение явно не закрывается одноранговым узлом, другой одноранговый узел (сторона сервера) не знает, следует ли ему закрывать его соответствующим образом до некоторого времени простоя.В любом случае, try finally может охватывать все случаи, чтобы обеспечить правильную очистку всех соединений.

0 голосов
/ 27 мая 2018

Жизненный цикл объекта не связан с циклом закрытия, то есть он может пережить его.Тем не менее объект будет возвращен сборщиком мусора, как только на него не будут ссылаться другие объекты (учтите, что в Scala 2.11 замыкания реализованы как анонимные внутренние классы).

Чтобы предотвратить ресурсдля утечек можно использовать так называемый шаблон кредита , в котором вы управляете жизненным циклом ресурса и следите за тем, чтобы он был освобожден после использования (или после возникновения ошибки):

def withConnection[A](manage: () => Connection)(use: Connection => A): A = {
  val connection = manage()
  try {
    use(connection)
  } finally {
    connection.close()
  }
}

rdd.foreachPartition(p =>
  withConnection(ConnectionFactory.createConnection(conf)) { conn =>
    p.foreach(item => {
      ??? // your code
    })
  }

Здесь вы можете найти более подробное объяснение схемы кредитования.

...