Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
92b90e62
Unverified
提交
92b90e62
authored
6 年前
作者:
Evgenij Ryazanov
提交者:
GitHub
6 年前
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1139 from katzyn/closer
Fix a memory leak caused by DatabaseCloser objects
上级
04564b6e
45dc8b56
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
107 行增加
和
47 行删除
+107
-47
Database.java
h2/src/main/org/h2/engine/Database.java
+4
-29
DelayedDatabaseCloser.java
h2/src/main/org/h2/engine/DelayedDatabaseCloser.java
+17
-18
OnExitDatabaseCloser.java
h2/src/main/org/h2/engine/OnExitDatabaseCloser.java
+86
-0
没有找到文件。
h2/src/main/org/h2/engine/Database.java
浏览文件 @
92b90e62
...
...
@@ -157,7 +157,7 @@ public class Database implements DataHandler {
private
int
powerOffCount
=
initialPowerOffCount
;
private
int
closeDelay
;
private
DatabaseCloser
delayedCloser
;
private
D
elayedD
atabaseCloser
delayedCloser
;
private
volatile
boolean
closing
;
private
boolean
ignoreCase
;
private
boolean
deleteFilesOnDisconnect
;
...
...
@@ -168,7 +168,6 @@ public class Database implements DataHandler {
private
boolean
referentialIntegrity
=
true
;
/** ie. the MVCC setting */
private
boolean
multiVersion
;
private
DatabaseCloser
closeOnExit
;
private
Mode
mode
=
Mode
.
getRegular
();
private
boolean
multiThreaded
;
private
int
maxOperationMemory
=
...
...
@@ -289,18 +288,7 @@ public class Database implements DataHandler {
try
{
open
(
traceLevelFile
,
traceLevelSystemOut
,
ci
);
if
(
closeAtVmShutdown
)
{
try
{
closeOnExit
=
new
DatabaseCloser
(
this
,
0
,
true
);
Runtime
.
getRuntime
().
addShutdownHook
(
closeOnExit
);
}
catch
(
IllegalStateException
e
)
{
// shutdown in progress - just don't register the handler
// (maybe an application wants to write something into a
// database at shutdown time)
}
catch
(
SecurityException
e
)
{
// applets may not do that - ignore
// Google App Engine doesn't allow
// to instantiate classes that extend Thread
}
OnExitDatabaseCloser
.
register
(
this
);
}
}
catch
(
Throwable
e
)
{
if
(
e
instanceof
OutOfMemoryError
)
{
...
...
@@ -1240,10 +1228,7 @@ public class Database implements DataHandler {
}
else
if
(
closeDelay
<
0
)
{
return
;
}
else
{
delayedCloser
=
new
DatabaseCloser
(
this
,
closeDelay
*
1000
,
false
);
delayedCloser
.
setName
(
"H2 Close Delay "
+
getShortName
());
delayedCloser
.
setDaemon
(
true
);
delayedCloser
.
start
();
delayedCloser
=
new
DelayedDatabaseCloser
(
this
,
closeDelay
*
1000
);
}
}
if
(
session
!=
systemSession
&&
...
...
@@ -1361,17 +1346,7 @@ public class Database implements DataHandler {
}
trace
.
info
(
"closed"
);
traceSystem
.
close
();
if
(
closeOnExit
!=
null
)
{
closeOnExit
.
reset
();
try
{
Runtime
.
getRuntime
().
removeShutdownHook
(
closeOnExit
);
}
catch
(
IllegalStateException
e
)
{
// ignore
}
catch
(
SecurityException
e
)
{
// applets may not do that - ignore
}
closeOnExit
=
null
;
}
OnExitDatabaseCloser
.
unregister
(
this
);
if
(
deleteFilesOnDisconnect
&&
persistent
)
{
deleteFilesOnDisconnect
=
false
;
try
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/DatabaseCloser.java
→
h2/src/main/org/h2/engine/D
elayedD
atabaseCloser.java
浏览文件 @
92b90e62
...
...
@@ -10,27 +10,28 @@ import java.lang.ref.WeakReference;
import
org.h2.message.Trace
;
/**
* This class is responsible to close a database
if the application did not
*
close a connection. A database closer object only exists if there is no user
*
connected to the
database.
* This class is responsible to close a database
after the specified delay. A
*
database closer object only exists if there is no user connected to the
* database.
*/
class
DatabaseCloser
extends
Thread
{
class
D
elayedD
atabaseCloser
extends
Thread
{
private
final
boolean
shutdownHook
;
private
final
Trace
trace
;
private
volatile
WeakReference
<
Database
>
databaseRef
;
private
int
delayInMillis
;
D
atabaseCloser
(
Database
db
,
int
delayInMillis
,
boolean
shutdownHook
)
{
this
.
databaseRef
=
new
WeakReference
<>(
db
);
D
elayedDatabaseCloser
(
Database
db
,
int
delayInMillis
)
{
databaseRef
=
new
WeakReference
<>(
db
);
this
.
delayInMillis
=
delayInMillis
;
this
.
shutdownHook
=
shutdownHook
;
trace
=
db
.
getTrace
(
Trace
.
DATABASE
);
setName
(
"H2 Close Delay "
+
db
.
getShortName
());
setDaemon
(
true
);
start
();
}
/**
* Stop and disable the database closer. This method is called after
the
*
database has been closed, or after a session
has been created.
* Stop and disable the database closer. This method is called after
a session
* has been created.
*/
void
reset
()
{
databaseRef
=
null
;
...
...
@@ -46,18 +47,16 @@ class DatabaseCloser extends Thread {
}
catch
(
Exception
e
)
{
// ignore InterruptedException
}
if
(
databaseRef
==
null
)
{
WeakReference
<
Database
>
ref
=
databaseRef
;
if
(
ref
==
null
||
ref
.
get
()
==
null
)
{
return
;
}
}
Database
database
=
null
;
WeakReference
<
Database
>
ref
=
this
.
databaseRef
;
if
(
ref
!=
null
)
{
database
=
ref
.
get
();
}
if
(
database
!=
null
)
{
Database
database
;
WeakReference
<
Database
>
ref
=
databaseRef
;
if
(
ref
!=
null
&&
(
database
=
ref
.
get
())
!=
null
)
{
try
{
database
.
close
(
shutdownHook
);
database
.
close
(
false
);
}
catch
(
RuntimeException
e
)
{
// this can happen when stopping a web application,
// if loading classes is no longer allowed
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/OnExitDatabaseCloser.java
0 → 100644
浏览文件 @
92b90e62
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
engine
;
import
java.util.WeakHashMap
;
import
org.h2.message.Trace
;
/**
* This class is responsible to close a database on JVM shutdown.
*/
class
OnExitDatabaseCloser
extends
Thread
{
private
static
final
WeakHashMap
<
Database
,
Void
>
DATABASES
=
new
WeakHashMap
<>();
private
static
OnExitDatabaseCloser
INSTANCE
;
static
synchronized
void
register
(
Database
db
)
{
DATABASES
.
put
(
db
,
null
);
if
(
INSTANCE
==
null
)
{
try
{
// Assign INSTANCE unconditionally to avoid further attempts to register a
// shutdown hook in case of exception.
Runtime
.
getRuntime
().
addShutdownHook
(
INSTANCE
=
new
OnExitDatabaseCloser
());
}
catch
(
IllegalStateException
e
)
{
// shutdown in progress - just don't register the handler
// (maybe an application wants to write something into a
// database at shutdown time)
}
catch
(
SecurityException
e
)
{
// applets may not do that - ignore
// Google App Engine doesn't allow
// to instantiate classes that extend Thread
}
}
}
static
synchronized
void
unregister
(
Database
db
)
{
DATABASES
.
remove
(
db
);
if
(
DATABASES
.
isEmpty
()
&&
INSTANCE
!=
null
)
{
try
{
Runtime
.
getRuntime
().
removeShutdownHook
(
INSTANCE
);
}
catch
(
IllegalStateException
e
)
{
// ignore
}
catch
(
SecurityException
e
)
{
// applets may not do that - ignore
}
INSTANCE
=
null
;
}
}
private
OnExitDatabaseCloser
()
{
}
@Override
public
void
run
()
{
RuntimeException
root
=
null
;
for
(
Database
database
:
DATABASES
.
keySet
())
{
try
{
database
.
close
(
true
);
}
catch
(
RuntimeException
e
)
{
// this can happen when stopping a web application,
// if loading classes is no longer allowed
// it would throw an IllegalStateException
try
{
database
.
getTrace
(
Trace
.
DATABASE
).
error
(
e
,
"could not close the database"
);
// if this was successful, we ignore the exception
// otherwise not
}
catch
(
Throwable
e2
)
{
e
.
addSuppressed
(
e2
);
if
(
root
==
null
)
{
root
=
e
;
}
else
{
root
.
addSuppressed
(
e
);
}
}
}
}
if
(
root
!=
null
)
{
throw
root
;
}
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论