2010-10-31 2 views
2

Я использовал 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 предел накладных расходов превысил» в separatedStrToBytes. Я допустил ошибки в обработке памяти здесь?

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

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

ответ

4

Ваш код работает очень хорошо против 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

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

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

+1

Хорошая идея. Как я могу использовать URI для разбора конечных точек UDP? Я могу извлечь строку IP из конечной точки, что делать дальше? Я не могу найти способ использовать пользовательскую схему, работающую с URI. – Basilevs

+0

Примеры того, что вы хотите проанализировать, были бы хорошей отправной точкой ... –

+0

1288495632 17 10.3.0.1 138 10.3.255.255 138 461 eth0 unknown – Basilevs

Смежные вопросы