Программа, использующая спящий режим, не заканчивается
Я создал программу, использующую Hibernate.
Программа достигает основной функции, тем не менее программа работает.
Интересно, происходит ли это при настройке SessionFactory
с использованием Hibernate версии 4.x.
Является ли способ неправильной настройки?
manual1_1_first_hibernate_apps.java
public static void main(String[] args) {
args[0] ="list";
if (args.length <= 0) {
System.err.println("argement was not given");
return;
}
manual1_1_first_hibernate_apps mgr = new manual1_1_first_hibernate_apps();
if (args[0].equals("store")) {
mgr.createAndStoreEvent("My Event", new Date());
}
else if (args[0].equals("list")) {
mgr.<Event>listEvents().stream()
.map(e -> "Event: " + e.getTitle() + " Time: " + e.getDate())
.forEach(System.out::println);
}
Util.getSessionFactory().close();
}
private <T> List<T> listEvents() {
Session session = Util.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<T> events = Util.autoCast(session.createQuery("from Event").list());
session.getTransaction().commit();
return events;
}
Util.java
private static final SessionFactory sessionFactory;
/**
* build a SessionFactory
*/
static {
try {
// Create the SessionFactory from hibernate.cfg.xml
// hibernate version lower than 4.x are as follows
// # it successful termination. but buildSessionFactory method is deprecated.
// sessionFactory = new Configuration().configure().buildSessionFactory();
// version 4.3 and later
// # it does not terminate. I manually terminated.
Configuration configuration = new Configuration().configure();
StandardServiceRegistry serviceRegistry =
new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
* @return built SessionFactory
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
Следующие фрагменты протокола консоли, когда программа завершает работу и использует метод buildSessionFactory.
2 08, 2014 8:42:25 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:derby:D:\Java\jdk1.7.0_03(x86)\db\bin\testdb]
но если вы не используете устаревший метод buildSessionFactory и завершаетесь (программа запущена), две выше указанные строки не отображаются.
СРЕДА:
Hibernate 4.3.1
DERBY
JRE 1.8
IntelliJ IDEA 13
Ответы
Ответ 1
Возможно, я решил эту проблему.
Я видел дамп потока после вызова Util.getSessionFactory(). close(), поток с именем "pool-2-thread-1" состоял из TIMED_WAITING (парковка).
Следующий сниппс
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.0-b69 mixed mode):
"DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x00000000020b9000 nid=0x3684 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"pool-2-thread-1" #15 prio=5 os_prio=0 tid=0x000000001bc27000 nid=0x3f0 waiting on condition [0x000000001ce6f000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000080be30a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
"derby.rawStoreDaemon" #14 daemon prio=5 os_prio=0 tid=0x000000001b059000 nid=0xa3c in Object.wait() [0x000000001ba1f000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000805f6190> (a org.apache.derby.impl.services.daemon.BasicDaemon)
at org.apache.derby.impl.services.daemon.BasicDaemon.rest(Unknown Source)
- locked <0x00000000805f6190> (a org.apache.derby.impl.services.daemon.BasicDaemon)
at org.apache.derby.impl.services.daemon.BasicDaemon.run(Unknown Source)
at java.lang.Thread.run(Thread.java:744)
"Timer-0" #13 daemon prio=5 os_prio=0 tid=0x000000001b08e800 nid=0x2160 in Object.wait() [0x000000001b6af000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000080608118> (a java.util.TaskQueue)
at java.lang.Object.wait(Object.java:502)
at java.util.TimerThread.mainLoop(Timer.java:526)
- locked <0x0000000080608118> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
Я думал, что причиной является поток с именем "pool-2-thread-1", созданный методом buildSessionFactory.
В результате сравнения двух методов buildSessionFactory я заметил, что ресурсы ServiceRegistry не выпущены.
Программа успешно завершена, выпуская ее.
Следующий код, добавляю.
Util.java
configuration.setSessionFactoryObserver(
new SessionFactoryObserver() {
@Override
public void sessionFactoryCreated(SessionFactory factory) {}
@Override
public void sessionFactoryClosed(SessionFactory factory) {
((StandardServiceRegistryImpl) serviceRegistry).destroy();
}
}
);
спасибо.
Ответ 2
Я встретил эту проблему и сегодня, и я нашел решение в конце вашего основного метода (или потока), вы должны закрыть сеанс Factory, например:
sessionFactory.close();
И тогда ваша программа завершится нормально.
Если вы используете JavaFX 8 в основном методе, добавьте:
@Override
public void stop() throws Exception {
sessionFactory.close();
}
Этот метод закрывает сеанс factory и уничтожает поток при выходе из программы.
Ответ 3
У меня была такая же проблема сегодня, но я нашел другое подобное решение:
В конце моего кода я вставил следующую строку:
StandardServiceRegistryBuilder.destroy(serviceRegistry);
И та-да! программа заканчивается.
Ответ 4
Та же проблема в 4.3.4.Final.
Теперь после добавления следующего кода проблема исчезла.
public class Service {
private SessionFactory factory;
private ServiceRegistry serviceRegistry;
public void initialize() throws Exception{
Configuration configuration = new Configuration();
configuration.configure("com/jeecourse/config/hibernate.cfg.xml");
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
factory = configuration.buildSessionFactory(serviceRegistry);
}
public void close() throws Exception{
if(serviceRegistry!= null) {
StandardServiceRegistryBuilder.destroy(serviceRegistry);
}
}
.....
Ответ 5
Кажется, что Hibernate 4.3.1 ввел ошибку. Я создаю соединение в своем приложении с помощью:
EntityManagerFactory connection = Persistence.createEntityManagerFactory(...)
но даже если метод createEntityManagerFactory
выходит из строя с исключением, реестр службы остается открытым. Однако, как вы могли видеть из приведенного выше кода, я не могу завершить свое приложение, потому что, поскольку метод не был успешным, переменная connection
не была назначена (она равна нулю), поэтому я не могу вызвать connection.close()
, который уничтожит сервисный реестр. Кажется, что это действительно ошибка, потому что как я могу освободить ресурсы, не прибегая к хакеру, например, используя определенные API-интерфейсы Hibernate из приложения JPA?
Ответ 6
У меня была одна и та же проблема. Я использовал Hibernate 4.1.1, и все работало нормально. Сегодня я обновился до Hibernate 4.3.1, и внезапно моя заявка больше не заканчивалась. Я немного исследовал и заметил, что версия 4.1.1 не имеет проблем с открытым EntityManagerFactory. Вот почему мое приложение всегда заканчивается. Это не так с версией 4.3.1. Поэтому я проверил свое приложение и убедился, что EntityManagerFactory был закрыт в конце (действительно, я действительно не закрывал его). Проблема решена для меня. Вы действительно уверены, что в вашем приложении ничего не осталось открытым? Надеюсь, это поможет.
Маркос
Ответ 7
Я встретил эту проблему и сегодня, и нашел, что решение вроде:
sessionFactory.close();
будет работать, если у вас есть
<property name="connection.pool_size">1</property>
Ответ 8
У меня была та же проблема, решение настолько простое, вы должны добавить это свойство в файл конфигурации
<property name="hibernate.c3p0.timeout">0</property>
Ответ 9
Я использую hibenate 5.2.12 с sqlite 3.20.1, управляя соединением вручную. В моем случае проблема заключалась в том, что не только администратор сущности должен был быть закрыт, но и менеджер сущностей factory.
С этими атрибутами:
EntityManager entityManager;
EntityTransaction entityTransaction;
Этот фрагмент используется при открытии БД и начале транзакции:
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, map);
entityManager = emf.createEntityManager(map);
entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
Этот снимок используется для фиксации транзакции и закрытия базы данных:
entityTransaction.commit();
if ( entityManager.isOpen() ) {
entityManager.close();
}
EntityManagerFactory emf = entityManager.getEntityManagerFactory();
if ( emf.isOpen() ) {
emf.close();
}
Теперь с emf.close();
мое приложение завершается так, как должно быть.