При использовании javassist из-под java-webstart возможны проблемы с поиском классов и/или с класслоадерами. В первом случае мы получим ошибку вроде javassist.NotFoundException, во втором что-нибудь вроде VerifyError.
От первого спасет ручное добавление классов в пул:
От второго: создание класса с указанием класс-лоадера:
вторник, 25 января 2011 г.
воскресенье, 23 января 2011 г.
Debug и JavaWS
Запускаем из консоли так:
set JAVAWS_VM_ARGS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8200" javaws http://xxx.xx/launch.jnlpИ аттачимся дебаггером.
суббота, 15 января 2011 г.
Type-safe Hibernate Criteria.
Пусть у нас есть класс User:
Обычно Criteria-api используют в таком стиле:
Мне кажется немного неправильным писать имена свойств в виде строк: могут возникнуть проблемы при рефакторинге.
На решение меня натолкнула библиотека jmock. В результате для getUser(*) получаем такой код:
Осталось реализовать (использую javassist и google-collections):
Обычно Criteria-api используют в таком стиле:
Мне кажется немного неправильным писать имена свойств в виде строк: могут возникнуть проблемы при рефакторинге.
На решение меня натолкнула библиотека jmock. В результате для getUser(*) получаем такой код:
Осталось реализовать (использую javassist и google-collections):
вторник, 4 января 2011 г.
Hibernate: org.hibernate.MappingException: Unknown entity ...
Если пользуетесь аннотациями для маппинга, и получаете ошибку Unknown entity, проверяйте в первую очередь, что импортируете @javax.persistence.Entity, а не @org.hibernate.annotations.Entity.
среда, 29 декабря 2010 г.
Пара regexp'ов для чистки проекта
Удаление строки author из javadoc:
/\*\*(\n.*$)*?(\n.*author.*$)(\n.*$)*?\n.*\*\/
Удаление пустых многострочных комментов:
\/\*\*\s*(\*\s*)*\*\/
/\*\*(\n.*$)*?(\n.*author.*$)(\n.*$)*?\n.*\*\/
Удаление пустых многострочных комментов:
\/\*\*\s*(\*\s*)*\*\/
вторник, 16 ноября 2010 г.
Spinner с четырьмя кнопками.
Понадобилось сделать спиннер, но с четырьмя кнопками. Две - для изменения значения на единицу и еще две - для изменения на 10.
Рассматривал два решения: поместить в спиннер в качестве эдитора другой спиннер или переписать BasicSpinnerUI (именно оно отвечает за создание и размещение компонентов спиннера). Остановился на втором.
Если наследоваться от BasicSpinnerUI, то получается все довольно просто. В installUI() добавляем на спиннер еще пару кнопок, а в createLayout() возвращаем наш layout, способный правильно расположить на пару кнопок больше.
И вот так можно протестировать:
Рассматривал два решения: поместить в спиннер в качестве эдитора другой спиннер или переписать BasicSpinnerUI (именно оно отвечает за создание и размещение компонентов спиннера). Остановился на втором.
Если наследоваться от BasicSpinnerUI, то получается все довольно просто. В installUI() добавляем на спиннер еще пару кнопок, а в createLayout() возвращаем наш layout, способный правильно расположить на пару кнопок больше.
И вот так можно протестировать:
пятница, 1 октября 2010 г.
Double-check locking.
Идея довольна проста. Пусть у нас есть Singleton, который дорог в создании. Создавать его может потребоваться, а может и нет. Хорошая идея создавать в тот момент, когда он понадобился в первый раз. Получаем код вроде такого:
Обратите внимание на synchonized при декларации метода: каждый раз, когда понадобится ссылка на Singleton, потоку придется захватить монитор, а это весьма дорогостоящая операция.
Если обращение к Singleton'у происходит часто, хотелось бы отказаться от захвата монитора в том случае, если объект уже создан и требуется только чтение.
Неправильное, но интуитивное решение:
Почему же оно неправильное? Причина кроется в специфике Java Memory Model, а именно в том, что обычные (не-volatile) переменные не являются точкой синхронизации.
Пусть у Singletona есть важное для нас поле value:
В худшем случае может происходить следующее:
Все потому, что для не-volatile переменных не гарантируется, что "happens-before order". Нужна некая точка синхронизации. Так как мы хотим отказаться от использования мониторов, то решение: пометить как volatile переменную singleton.
Обратите внимание на synchonized при декларации метода: каждый раз, когда понадобится ссылка на Singleton, потоку придется захватить монитор, а это весьма дорогостоящая операция.
Если обращение к Singleton'у происходит часто, хотелось бы отказаться от захвата монитора в том случае, если объект уже создан и требуется только чтение.
Неправильное, но интуитивное решение:
Почему же оно неправильное? Причина кроется в специфике Java Memory Model, а именно в том, что обычные (не-volatile) переменные не являются точкой синхронизации.
Пусть у Singletona есть важное для нас поле value:
В худшем случае может происходить следующее:
NN | первый поток | второй поток |
---|---|---|
1 | - | getSingleton() |
2 | - | singleton = new Singleton() и value=42 |
3 | - | переменная singleton скидывается в основную память |
4 | getSingleton() | - |
5 | так как переменная singleton не null, в synchronized блок не заходим | |
6 | singleton.value==0 (значение по умолчанию, так как новое значение не было записано еще в основную память) | - |
Все потому, что для не-volatile переменных не гарантируется, что "happens-before order". Нужна некая точка синхронизации. Так как мы хотим отказаться от использования мониторов, то решение: пометить как volatile переменную singleton.
Подписаться на:
Сообщения (Atom)