Где утечка памяти? - PullRequest
       8

Где утечка памяти?

2 голосов
/ 31 октября 2010

Я использовал InetAddress для разбора IP-адресов, но теперь необходимо сохранить имя хоста, если IP-адрес недоступен.Поэтому я ввел класс Host.

case class Host(name:String, ip:InetAddress) {
    import Host.{addressToBytes, compareSeqs}
    override def toString:String = if (ip!=null) {ip.getHostName} else {name}
}

object Host {
    implicit def stringToPattern(s:String): Pattern = Pattern.compile(s)
    val separators = Seq[Pattern]("\\.", ":")
    def separatedStrToBytes(s:String, separator:Pattern): Array[Byte] = {
        val fields = separator.split(s)
        var rv = new Array[Byte](fields.length);
        fields.map(_.toInt.toByte).copyToArray(rv, 0)
        rv
    }
    implicit def strToBytes(s:String): Array[Byte] = {
        for (sep <- separators)
            if (sep.matcher(s).find())
                return separatedStrToBytes(s, sep)
        null
    }
    implicit def strToHost(s:String):Host = {
        var name = s
        var ip:InetAddress = null
        try {
            val bytes = strToBytes(s)
            if (bytes != null) { 
                ip = InetAddress.getByAddress(bytes)
//              println( "parsed ip: "+s)
            }
        } catch {
            case e:UnknownHostException =>
        }
        if (ip==null) {
            ip = InetAddress.getByName(s)
        }
        new Host(name, ip)
    }
}

. С этим изменением у моего программного обеспечения произошел сбой с "java.lang.OutOfMemoryError: Превышен предел издержек GC" в detaStrToBytes.Я сделал здесь какие-либо ошибки обработки памяти?

Я ценю любые комментарии по дизайну.Мне не удалось сократить разбор из-за необходимости использования массива [Byte] в качестве аргумента InetAddress.getByAddress.На целевой платформе имеется Scala 2.7.7.

EDIT : я заменил синтаксический анализ на фиктивные и обнаружил, что моя программа все еще не может обработать несколько мегабайт проанализированных данных позже в других местах.Каждая замена String.split (s: String) на Pattern.split (s: String) и предварительно скомпилированный шаблон делает его немного длиннее.Это не решает мою проблему, но этот вопрос может быть закрыт сейчас.Мне все еще нужны комментарии дизайна, хотя.

Ответы [ 2 ]

4 голосов
/ 31 октября 2010

Ваш код прекрасно работает с 2.8.0 (вам следует перейти на него, так как он уже окончательный и достаточно стабильный) - OutOfMemory не обнаружен.

Некоторые оптимизации, которые вы просили:

implicit def strToBytes(s:String)= (for {separator <- separators find(_.matcher(s).find)} yield separatedStrToBytes(s, separator)) getOrElse null

implicit def separatedStrToBytes(s:String, separator:Pattern) = s split separator.pattern map(Integer.parseInt(_).toByte)

scala> import Host._
import Host._
scala> strToBytes("127.0.0.1")
res9: Array[Byte] = Array(127, 0, 0, 1)
1 голос
/ 31 октября 2010

Нет необходимости вручную анализировать URI, как это, просто используйте уже существующий класс URI из стандартной библиотеки Java: http://download.oracle.com/javase/6/docs/api/java/net/URI.html

не используйте класс URL, ни при каких обстоятельствах. У него есть сумасшедший алгоритм хеширования, который сначала разрешает имя хоста в IP-адрес, что является одной из главных причин, почему так много Java-инструментов, использующих URL (таких как менеджер обновлений Eclipse), очень медленно запускаются, когда вы этого не делаете есть сетевое соединение

...