Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
6efe6e7f
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
6efe6e7f
编写于
1月 21, 2015
作者:
P
plevart
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8068427: Hashtable deserialization reconstitutes table with wrong capacity
Reviewed-by: mduigou, martin, chegar, dfuchs
上级
3e254042
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
133 addition
and
12 deletion
+133
-12
src/share/classes/java/util/Hashtable.java
src/share/classes/java/util/Hashtable.java
+23
-12
test/java/util/Hashtable/DeserializedLength.java
test/java/util/Hashtable/DeserializedLength.java
+110
-0
未找到文件。
src/share/classes/java/util/Hashtable.java
浏览文件 @
6efe6e7f
...
@@ -1132,10 +1132,10 @@ public class Hashtable<K,V>
...
@@ -1132,10 +1132,10 @@ public class Hashtable<K,V>
Entry
<
Object
,
Object
>
entryStack
=
null
;
Entry
<
Object
,
Object
>
entryStack
=
null
;
synchronized
(
this
)
{
synchronized
(
this
)
{
// Write out the
length, threshold, loadf
actor
// Write out the
threshold and loadF
actor
s
.
defaultWriteObject
();
s
.
defaultWriteObject
();
// Write out
length,
count of elements
// Write out
the length and
count of elements
s
.
writeInt
(
table
.
length
);
s
.
writeInt
(
table
.
length
);
s
.
writeInt
(
count
);
s
.
writeInt
(
count
);
...
@@ -1165,22 +1165,33 @@ public class Hashtable<K,V>
...
@@ -1165,22 +1165,33 @@ public class Hashtable<K,V>
private
void
readObject
(
java
.
io
.
ObjectInputStream
s
)
private
void
readObject
(
java
.
io
.
ObjectInputStream
s
)
throws
IOException
,
ClassNotFoundException
throws
IOException
,
ClassNotFoundException
{
{
// Read in the
length, threshold, and loadf
actor
// Read in the
threshold and loadF
actor
s
.
defaultReadObject
();
s
.
defaultReadObject
();
// Validate loadFactor (ignore threshold - it will be re-computed)
if
(
loadFactor
<=
0
||
Float
.
isNaN
(
loadFactor
))
throw
new
StreamCorruptedException
(
"Illegal Load: "
+
loadFactor
);
// Read the original length of the array and number of elements
// Read the original length of the array and number of elements
int
origlength
=
s
.
readInt
();
int
origlength
=
s
.
readInt
();
int
elements
=
s
.
readInt
();
int
elements
=
s
.
readInt
();
// Compute new size with a bit of room 5% to grow but
// Validate # of elements
// no larger than the original size. Make the length
if
(
elements
<
0
)
throw
new
StreamCorruptedException
(
"Illegal # of Elements: "
+
elements
);
// Clamp original length to be more than elements / loadFactor
// (this is the invariant enforced with auto-growth)
origlength
=
Math
.
max
(
origlength
,
(
int
)(
elements
/
loadFactor
)
+
1
);
// Compute new length with a bit of room 5% + 3 to grow but
// no larger than the clamped original length. Make the length
// odd if it's large enough, this helps distribute the entries.
// odd if it's large enough, this helps distribute the entries.
// Guard against the length ending up zero, that's not valid.
// Guard against the length ending up zero, that's not valid.
int
length
=
(
int
)(
elements
*
loadFactor
)
+
(
elements
/
20
)
+
3
;
int
length
=
(
int
)(
(
elements
+
elements
/
20
)
/
loadFactor
)
+
3
;
if
(
length
>
elements
&&
(
length
&
1
)
==
0
)
if
(
length
>
elements
&&
(
length
&
1
)
==
0
)
length
--;
length
--;
if
(
origlength
>
0
&&
length
>
origlength
)
length
=
Math
.
min
(
length
,
origlength
);
length
=
origlength
;
table
=
new
Entry
<?,?>[
length
];
table
=
new
Entry
<?,?>[
length
];
threshold
=
(
int
)
Math
.
min
(
length
*
loadFactor
,
MAX_ARRAY_SIZE
+
1
);
threshold
=
(
int
)
Math
.
min
(
length
*
loadFactor
,
MAX_ARRAY_SIZE
+
1
);
count
=
0
;
count
=
0
;
...
@@ -1191,7 +1202,7 @@ public class Hashtable<K,V>
...
@@ -1191,7 +1202,7 @@ public class Hashtable<K,V>
K
key
=
(
K
)
s
.
readObject
();
K
key
=
(
K
)
s
.
readObject
();
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
V
value
=
(
V
)
s
.
readObject
();
V
value
=
(
V
)
s
.
readObject
();
// sync
h could be
eliminated for performance
// sync
is
eliminated for performance
reconstitutionPut
(
table
,
key
,
value
);
reconstitutionPut
(
table
,
key
,
value
);
}
}
}
}
...
@@ -1203,9 +1214,9 @@ public class Hashtable<K,V>
...
@@ -1203,9 +1214,9 @@ public class Hashtable<K,V>
*
*
* <p>This differs from the regular put method in several ways. No
* <p>This differs from the regular put method in several ways. No
* checking for rehashing is necessary since the number of elements
* checking for rehashing is necessary since the number of elements
* initially in the table is known. The modCount is not incremented
* initially in the table is known. The modCount is not incremented
and
*
because we are creating a new instance. Also, no return value
*
there's no synchronization because we are creating a new instance.
* is needed.
*
Also, no return value
is needed.
*/
*/
private
void
reconstitutionPut
(
Entry
<?,?>[]
tab
,
K
key
,
V
value
)
private
void
reconstitutionPut
(
Entry
<?,?>[]
tab
,
K
key
,
V
value
)
throws
StreamCorruptedException
throws
StreamCorruptedException
...
...
test/java/util/Hashtable/DeserializedLength.java
0 → 100644
浏览文件 @
6efe6e7f
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
java.io.*
;
import
java.lang.reflect.Field
;
import
java.util.Hashtable
;
/**
* @test
* @bug 8068427
* @summary Hashtable deserialization reconstitutes table with wrong capacity
*/
public
class
DeserializedLength
{
static
boolean
testDeserializedLength
(
int
elements
,
float
loadFactor
)
throws
Exception
{
// construct Hashtable with minimal initial capacity and given loadFactor
Hashtable
<
Integer
,
Integer
>
ht1
=
new
Hashtable
<>(
1
,
loadFactor
);
// add given number of unique elements
for
(
int
i
=
0
;
i
<
elements
;
i
++)
{
ht1
.
put
(
i
,
i
);
}
// serialize and deserialize into a deep clone
Hashtable
<
Integer
,
Integer
>
ht2
=
serialClone
(
ht1
);
// compare lengths of internal tables
Object
[]
table1
=
(
Object
[])
hashtableTableField
.
get
(
ht1
);
Object
[]
table2
=
(
Object
[])
hashtableTableField
.
get
(
ht2
);
assert
table1
!=
null
;
assert
table2
!=
null
;
int
minLength
=
(
int
)
(
ht1
.
size
()
/
loadFactor
)
+
1
;
int
maxLength
=
minLength
*
2
;
boolean
ok
=
(
table2
.
length
>=
minLength
&&
table2
.
length
<=
maxLength
);
System
.
out
.
printf
(
"%7d %5.2f %7d %7d %7d...%7d %s\n"
,
ht1
.
size
(),
loadFactor
,
table1
.
length
,
table2
.
length
,
minLength
,
maxLength
,
(
ok
?
"OK"
:
"NOT-OK"
)
);
return
ok
;
}
static
<
T
>
T
serialClone
(
T
o
)
throws
IOException
,
ClassNotFoundException
{
ByteArrayOutputStream
bos
=
new
ByteArrayOutputStream
();
try
(
ObjectOutputStream
oos
=
new
ObjectOutputStream
(
bos
))
{
oos
.
writeObject
(
o
);
}
@SuppressWarnings
(
"unchecked"
)
T
clone
=
(
T
)
new
ObjectInputStream
(
new
ByteArrayInputStream
(
bos
.
toByteArray
())).
readObject
();
return
clone
;
}
private
static
final
Field
hashtableTableField
;
static
{
try
{
hashtableTableField
=
Hashtable
.
class
.
getDeclaredField
(
"table"
);
hashtableTableField
.
setAccessible
(
true
);
}
catch
(
NoSuchFieldException
e
)
{
throw
new
Error
(
e
);
}
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
boolean
ok
=
true
;
System
.
out
.
printf
(
"Results:\n"
+
" ser. deser.\n"
+
" size load lentgh length valid range ok?\n"
+
"------- ----- ------- ------- ----------------- ------\n"
);
for
(
int
elements
:
new
int
[]{
10
,
50
,
500
,
5000
})
{
for
(
float
loadFactor
:
new
float
[]{
0.15f
,
0.5f
,
0.75f
,
1.0f
,
2.5f
})
{
ok
&=
testDeserializedLength
(
elements
,
loadFactor
);
}
}
if
(!
ok
)
{
throw
new
AssertionError
(
"Test failed."
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录