пятница, 21 мая 2010 г.

Нестабильность Enum.hashCode() и HashMap

На днях обнаружилась любопытная особенность enum'ов. В коде сервера я использовал ScalableHashMap для хранения некоторых данных, где ключом является enum. ScalableHashMap - это специальная реализация хешмапа для сервера Reddwarf.

После первого запуска сервера и инициализации карты всё работало замечательно.
Потом ScalableHashMap был сериализован и сохранен на диск.
Дальше сервер был перезагружен, и ScalableHashMap десериализован с диска.
Делаю ScalableHashMap.get(key) и... получаю null!
Вывожу ScalableHashMap на экран с помощью toString() - там всё есть! Но почему-то он не хочет доставать записанные данные.

Оказалось загвоздка вот в чем:
Enum использует hashCode(), унаследованный от Object(). Следовательно, при перезапуске сервера меняются адреса ссылок, соответственно меняются хеш-коды объектов. И из карты невозможно вытащить объект с новым хеш-кодом, сохраненный по старому хеш-коду!

вторник, 20 апреля 2010 г.

Sun Tech Days 2010

"Как жаль, что эта конференция проходит не в Москве" - думал я в прошлом году, когда понял, что не получится внезапно поехать на Sun Tech Days 2009.
"Как хорошо, что эта конференция проходит не в Москве" - думал я в этом году, прогуливаясь по северной столице по прекрасной погоде, любуясь красотами этого замечательного города и предвкушая много нового и интересного на конференции.

пятница, 19 марта 2010 г.

Как получить Unix PID в Java-приложении

Для контроля работоспособности сервера я использовал monit. Очень удобная штука, единственной сложностью оказалось то, что monit требовал, чтобы приложение писало свой PID в файл.

В результате недолгих поисков был найден способ узнать PID: Java-приложение должно запустить процесс, который выведет PID родителя. Один из самых простых вариантов - выполнить команду "echo $PPID" командного интерпретатора bash ($PPID - переменная, хранящая PID родительского процесса).

import java.io.*;

public class UnixUtils {

public static String getPid() throws IOException, InterruptedException {

// Запускаем bash с параметром -c, что означает "выполнить команду"
// Командой будет "echo $PPID" - вывести PID родительского процесса
ProcessBuilder pb=new ProcessBuilder("/bin/bash", "-c", "echo $PPID");

Process pr=pb.start();
pr.waitFor();
// Если процесс завершился успешно, вернул код 0, считаем, что он нам вывел
if (pr.exitValue() == 0) {
BufferedReader outReader=new BufferedReader(new InputStreamReader(pr.getInputStream()));
return outReader.readLine().trim();
} else {
return null;
}
}
}

понедельник, 15 февраля 2010 г.

Цветное логирование

Цвета порой очень облегчают восприятие информации.
Попытка раскрасить логи была сделана сначала просто забавы ради, но потом, когда я понял, насколько это удобно, уже не мог работать с однообразными одноцветными логами.

Изначально логи раскрашивались с помощью расширения для logback, но потом оказалось, что удобней писать логи обычным текстом, а раскрашивать - уже при просмотре.


понедельник, 11 января 2010 г.

Tomcat и CharConversionException

При разработке сервлета под Tomcat столкнулся со следующей проблемой и долго мучился:

HTTP Status 500 -


type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
java.io.CharConversionException: Not an ISO 8859-1 character: з
javax.servlet.ServletOutputStream.print(ServletOutputStream.java:89)
dating.servlet.TestServlet.service(TestServlet.java:77)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

note The full stack trace of the root cause is available in the Apache Tomcat/6.0.20 logs.

Apache Tomcat/6.0.20