Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell11
提交
d39a295f
D
dragonwell11
项目概览
openanolis
/
dragonwell11
通知
7
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell11
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d39a295f
编写于
11月 06, 2017
作者:
M
mchung
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8164512: Replace ClassLoader use of finalizer with phantom reference to unload native library
Reviewed-by: alanb, bchristi, kbarrett, dholmes, plevart
上级
7f36998f
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
475 addition
and
154 deletion
+475
-154
make/mapfiles/libjava/mapfile-vers
make/mapfiles/libjava/mapfile-vers
+2
-2
make/mapfiles/libjava/reorder-sparc
make/mapfiles/libjava/reorder-sparc
+2
-2
make/mapfiles/libjava/reorder-sparcv9
make/mapfiles/libjava/reorder-sparcv9
+2
-2
make/mapfiles/libjava/reorder-x86
make/mapfiles/libjava/reorder-x86
+2
-2
make/test/JtregNativeJdk.gmk
make/test/JtregNativeJdk.gmk
+1
-0
src/java.base/share/classes/java/lang/ClassLoader.java
src/java.base/share/classes/java/lang/ClassLoader.java
+199
-122
src/java.base/share/classes/java/lang/Runtime.java
src/java.base/share/classes/java/lang/Runtime.java
+5
-2
src/java.base/share/classes/java/lang/System.java
src/java.base/share/classes/java/lang/System.java
+4
-2
src/java.base/share/native/libjava/ClassLoader.c
src/java.base/share/native/libjava/ClassLoader.c
+18
-20
test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java
...ava/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java
+129
-0
test/jdk/java/lang/ClassLoader/nativeLibrary/libnativeLibraryTest.c
...ava/lang/ClassLoader/nativeLibrary/libnativeLibraryTest.c
+74
-0
test/jdk/java/lang/ClassLoader/nativeLibrary/p/Test.java
test/jdk/java/lang/ClassLoader/nativeLibrary/p/Test.java
+37
-0
未找到文件。
make/mapfiles/libjava/mapfile-vers
浏览文件 @
d39a295f
...
...
@@ -130,8 +130,8 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_defineClass2;
Java_java_lang_ClassLoader_findBuiltinLib;
Java_java_lang_ClassLoader_findLoadedClass0;
Java_java_lang_ClassLoader_00024NativeLibrary_find;
Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_find
Entry
;
Java_java_lang_ClassLoader_00024NativeLibrary_load
0
;
Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Double_longBitsToDouble;
...
...
make/mapfiles/libjava/reorder-sparc
浏览文件 @
d39a295f
...
...
@@ -48,8 +48,8 @@ text: .text%Java_java_io_FileInputStream_available0;
text: .text%Java_java_io_FileInputStream_close0;
text: .text%Java_java_lang_System_mapLibraryName;
text: .text%Java_java_io_UnixFileSystem_getBooleanAttributes0;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load
0
;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find
Entry
;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2;
text: .text%Java_java_io_UnixFileSystem_list;
text: .text%JNU_ClassString;
...
...
make/mapfiles/libjava/reorder-sparcv9
浏览文件 @
d39a295f
...
...
@@ -57,8 +57,8 @@ text: .text%JNU_CopyObjectArray;
text: .text%Java_java_io_UnixFileSystem_getBooleanAttributes0;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
text: .text%Java_java_lang_System_mapLibraryName;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load
0
;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find
Entry
;
text: .text%Java_java_io_UnixFileSystem_getLength;
text: .text%Java_java_lang_Object_getClass;
text: .text%Java_java_lang_ClassLoader_defineClass0;
...
...
make/mapfiles/libjava/reorder-x86
浏览文件 @
d39a295f
...
...
@@ -50,8 +50,8 @@ text: .text%Java_java_lang_ClassLoader_findBootstrapClass;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
text: .text%Java_java_lang_System_mapLibraryName;
text: .text%cpchars: OUTPUTDIR/System.o;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load
0
;
text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find
Entry
;
text: .text%Java_java_lang_Float_floatToRawIntBits;
text: .text%Java_java_lang_Double_doubleToRawLongBits;
text: .text%Java_java_io_FileInputStream_open0;
...
...
make/test/JtregNativeJdk.gmk
浏览文件 @
d39a295f
...
...
@@ -44,6 +44,7 @@ $(eval $(call IncludeCustomExtension, test/JtregNativeJdk.gmk))
# Add more directories here when needed.
BUILD_JDK_JTREG_NATIVE_SRC += \
$(TOPDIR)/test/jdk/native_sanity \
$(TOPDIR)/test/jdk/java/lang/ClassLoader/nativeLibrary \
$(TOPDIR)/test/jdk/java/lang/String/nativeEncoding \
#
...
...
src/java.base/share/classes/java/lang/ClassLoader.java
浏览文件 @
d39a295f
...
...
@@ -37,17 +37,20 @@ import java.security.CodeSource;
import
java.security.PrivilegedAction
;
import
java.security.ProtectionDomain
;
import
java.security.cert.Certificate
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Deque
;
import
java.util.Enumeration
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Hashtable
;
import
java.util.LinkedList
;
import
java.util.Map
;
import
java.util.NoSuchElementException
;
import
java.util.Objects
;
import
java.util.Set
;
import
java.util.Spliterator
;
import
java.util.Spliterators
;
import
java.util.Stack
;
import
java.util.Vector
;
import
java.util.WeakHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
...
...
@@ -58,9 +61,9 @@ import java.util.stream.StreamSupport;
import
jdk.internal.perf.PerfCounter
;
import
jdk.internal.loader.BootLoader
;
import
jdk.internal.loader.ClassLoaders
;
import
jdk.internal.misc.SharedSecrets
;
import
jdk.internal.misc.Unsafe
;
import
jdk.internal.misc.VM
;
import
jdk.internal.ref.CleanerFactory
;
import
jdk.internal.reflect.CallerSensitive
;
import
jdk.internal.reflect.Reflection
;
import
sun.reflect.misc.ReflectUtil
;
...
...
@@ -2375,74 +2378,160 @@ public abstract class ClassLoader {
* @since 1.2
*/
static
class
NativeLibrary
{
// opaque handle to native library, used in native code.
long
handle
;
// the version of JNI environment the native library requires.
private
int
jniVersion
;
// the class from which the library is loaded, also indicates
// the loader this native library belongs.
private
Class
<?>
fromClass
;
final
Class
<?>
fromClass
;
// the canonicalized name of the native library.
// or static library name
String
name
;
final
String
name
;
// Indicates if the native library is linked into the VM
boolean
isBuiltin
;
// Indicates if the native library is loaded
boolean
loaded
;
native
void
load
(
String
name
,
boolean
isBuiltin
);
final
boolean
isBuiltin
;
// opaque handle to native library, used in native code.
long
handle
;
// the version of JNI environment the native library requires.
int
jniVersion
;
native
long
find
(
String
name
);
native
void
unload
(
String
name
,
boolean
isBuiltin
);
native
boolean
load0
(
String
name
,
boolean
isBuiltin
);
public
NativeLibrary
(
Class
<?>
fromClass
,
String
name
,
boolean
isBuiltin
)
{
native
long
findEntry
(
String
name
);
NativeLibrary
(
Class
<?>
fromClass
,
String
name
,
boolean
isBuiltin
)
{
this
.
name
=
name
;
this
.
fromClass
=
fromClass
;
this
.
isBuiltin
=
isBuiltin
;
}
@SuppressWarnings
(
"deprecation"
)
protected
void
finalize
()
{
/*
* Loads the native library and registers for cleanup when its
* associated class loader is unloaded
*/
boolean
load
()
{
if
(
handle
!=
0
)
{
throw
new
InternalError
(
"Native library "
+
name
+
" has been loaded"
);
}
if
(!
load0
(
name
,
isBuiltin
))
return
false
;
// register the class loader for cleanup when unloaded
// built class loaders are never unloaded
ClassLoader
loader
=
fromClass
.
getClassLoader
();
if
(
loader
!=
null
&&
loader
!=
getBuiltinPlatformClassLoader
()
&&
loader
!=
getBuiltinAppClassLoader
())
{
CleanerFactory
.
cleaner
().
register
(
loader
,
new
Unloader
(
name
,
handle
,
isBuiltin
));
}
return
true
;
}
static
boolean
loadLibrary
(
Class
<?>
fromClass
,
String
name
,
boolean
isBuiltin
)
{
ClassLoader
loader
=
fromClass
==
null
?
null
:
fromClass
.
getClassLoader
();
synchronized
(
loadedLibraryNames
)
{
if
(
fromClass
.
getClassLoader
()
!=
null
&&
loaded
)
{
this
.
fromClass
=
null
;
// no context when unloaded
Map
<
String
,
NativeLibrary
>
libs
=
loader
!=
null
?
loader
.
nativeLibraries
()
:
systemNativeLibraries
();
if
(
libs
.
containsKey
(
name
))
{
return
true
;
}
/* remove the native library name */
int
size
=
loadedLibraryNames
.
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
(
name
.
equals
(
loadedLibraryNames
.
elementAt
(
i
)))
{
loadedLibraryNames
.
removeElementAt
(
i
);
break
;
if
(
loadedLibraryNames
.
contains
(
name
))
{
throw
new
UnsatisfiedLinkError
(
"Native Library "
+
name
+
" already loaded in another classloader"
);
}
/*
* When a library is being loaded, JNI_OnLoad function can cause
* another loadLibrary invocation that should succeed.
*
* We use a static stack to hold the list of libraries we are
* loading because this can happen only when called by the
* same thread because Runtime.load and Runtime.loadLibrary
* are synchronous.
*
* If there is a pending load operation for the library, we
* immediately return success; otherwise, we raise
* UnsatisfiedLinkError.
*/
for
(
NativeLibrary
lib
:
nativeLibraryContext
)
{
if
(
name
.
equals
(
lib
.
name
))
{
if
(
loader
==
lib
.
fromClass
.
getClassLoader
())
{
return
true
;
}
else
{
throw
new
UnsatisfiedLinkError
(
"Native Library "
+
name
+
" is being loaded in another classloader"
);
}
}
/* unload the library. */
ClassLoader
.
nativeLibraryContext
.
push
(
this
);
try
{
unload
(
name
,
isBuiltin
);
}
finally
{
ClassLoader
.
nativeLibraryContext
.
pop
();
}
}
NativeLibrary
lib
=
new
NativeLibrary
(
fromClass
,
name
,
isBuiltin
);
// load the native library
nativeLibraryContext
.
push
(
lib
);
try
{
if
(!
lib
.
load
())
return
false
;
}
finally
{
nativeLibraryContext
.
pop
();
}
// register the loaded native library
loadedLibraryNames
.
add
(
name
);
libs
.
put
(
name
,
lib
);
}
return
true
;
}
// Invoked in the VM to determine the context class in
// JNI_Load/JNI_Unload
// Invoked in the VM to determine the context class in JNI_OnLoad
// and JNI_OnUnload
static
Class
<?>
getFromClass
()
{
return
ClassLoader
.
nativeLibraryContext
.
peek
().
fromClass
;
return
nativeLibraryContext
.
peek
().
fromClass
;
}
}
// All native library names we've loaded.
private
static
Vector
<
String
>
loadedLibraryNames
=
new
Vector
<>();
// native libraries being loaded
static
Deque
<
NativeLibrary
>
nativeLibraryContext
=
new
LinkedList
<>();
// Native libraries belonging to system classes.
private
static
Vector
<
NativeLibrary
>
systemNativeLibraries
=
new
Vector
<>();
/*
* The run() method will be invoked when this class loader becomes
* phantom reachable to unload the native library.
*/
static
class
Unloader
implements
Runnable
{
// This represents the context when a native library is unloaded
// and getFromClass() will return null,
static
final
NativeLibrary
UNLOADER
=
new
NativeLibrary
(
null
,
"dummy"
,
false
);
final
String
name
;
final
long
handle
;
final
boolean
isBuiltin
;
Unloader
(
String
name
,
long
handle
,
boolean
isBuiltin
)
{
if
(
handle
==
0
)
{
throw
new
IllegalArgumentException
(
"Invalid handle for native library "
+
name
);
}
// Native libraries associated with the class loader.
private
Vector
<
NativeLibrary
>
nativeLibraries
=
new
Vector
<>();
this
.
name
=
name
;
this
.
handle
=
handle
;
this
.
isBuiltin
=
isBuiltin
;
}
@Override
public
void
run
()
{
synchronized
(
loadedLibraryNames
)
{
/* remove the native library name */
loadedLibraryNames
.
remove
(
name
);
nativeLibraryContext
.
push
(
UNLOADER
);
try
{
unload
(
name
,
isBuiltin
,
handle
);
}
finally
{
nativeLibraryContext
.
pop
();
}
// native libraries being loaded/unloaded.
private
static
Stack
<
NativeLibrary
>
nativeLibraryContext
=
new
Stack
<>();
}
}
}
// JNI FindClass expects the caller class if invoked from JNI_OnLoad
// and JNI_OnUnload is NativeLibrary class
static
native
void
unload
(
String
name
,
boolean
isBuiltin
,
long
handle
);
}
// The paths searched for libraries
private
static
String
usr_paths
[];
...
...
@@ -2455,7 +2544,7 @@ public abstract class ClassLoader {
int
psCount
=
0
;
if
(
ClassLoaderHelper
.
allowsQuotedPathElements
&&
ldPath
.
indexOf
(
'\"'
)
>=
0
)
{
ldPath
.
indexOf
(
'\"'
)
>=
0
)
{
// First, remove quotes put around quoted parts of paths.
// Second, use a quotation mark as a new path separator.
// This will preserve any quoted old path separators.
...
...
@@ -2465,7 +2554,7 @@ public abstract class ClassLoader {
char
ch
=
ldPath
.
charAt
(
i
);
if
(
ch
==
'\"'
)
{
while
(++
i
<
ldLen
&&
(
ch
=
ldPath
.
charAt
(
i
))
!=
'\"'
)
{
(
ch
=
ldPath
.
charAt
(
i
))
!=
'\"'
)
{
buf
[
bufLen
++]
=
ch
;
}
}
else
{
...
...
@@ -2481,7 +2570,7 @@ public abstract class ClassLoader {
ps
=
'\"'
;
}
else
{
for
(
int
i
=
ldPath
.
indexOf
(
ps
);
i
>=
0
;
i
=
ldPath
.
indexOf
(
ps
,
i
+
1
))
{
i
=
ldPath
.
indexOf
(
ps
,
i
+
1
))
{
psCount
++;
}
}
...
...
@@ -2491,11 +2580,11 @@ public abstract class ClassLoader {
for
(
int
j
=
0
;
j
<
psCount
;
++
j
)
{
int
pathEnd
=
ldPath
.
indexOf
(
ps
,
pathStart
);
paths
[
j
]
=
(
pathStart
<
pathEnd
)
?
ldPath
.
substring
(
pathStart
,
pathEnd
)
:
"."
;
ldPath
.
substring
(
pathStart
,
pathEnd
)
:
"."
;
pathStart
=
pathEnd
+
1
;
}
paths
[
psCount
]
=
(
pathStart
<
ldLen
)
?
ldPath
.
substring
(
pathStart
,
ldLen
)
:
"."
;
ldPath
.
substring
(
pathStart
,
ldLen
)
:
"."
;
return
paths
;
}
...
...
@@ -2520,7 +2609,7 @@ public abstract class ClassLoader {
File
libfile
=
new
File
(
libfilename
);
if
(!
libfile
.
isAbsolute
())
{
throw
new
UnsatisfiedLinkError
(
"ClassLoader.findLibrary failed to return an absolute path: "
+
libfilename
);
"ClassLoader.findLibrary failed to return an absolute path: "
+
libfilename
);
}
if
(
loadLibrary0
(
fromClass
,
libfile
))
{
return
;
...
...
@@ -2551,10 +2640,11 @@ public abstract class ClassLoader {
}
}
// Oops, it failed
throw
new
UnsatisfiedLinkError
(
"no "
+
name
+
" in java.library.path"
);
throw
new
UnsatisfiedLinkError
(
"no "
+
name
+
" in java.library.path: "
+
Arrays
.
toString
(
usr_paths
));
}
static
native
String
findBuiltinLib
(
String
name
);
private
static
native
String
findBuiltinLib
(
String
name
);
private
static
boolean
loadLibrary0
(
Class
<?>
fromClass
,
final
File
file
)
{
// Check to see if we're attempting to access a static library
...
...
@@ -2575,86 +2665,73 @@ public abstract class ClassLoader {
return
false
;
}
}
ClassLoader
loader
=
(
fromClass
==
null
)
?
null
:
fromClass
.
getClassLoader
();
Vector
<
NativeLibrary
>
libs
=
loader
!=
null
?
loader
.
nativeLibraries
:
systemNativeLibraries
;
synchronized
(
libs
)
{
int
size
=
libs
.
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
NativeLibrary
lib
=
libs
.
elementAt
(
i
);
if
(
name
.
equals
(
lib
.
name
))
{
return
true
;
}
}
return
NativeLibrary
.
loadLibrary
(
fromClass
,
name
,
isBuiltin
);
}
/*
* Invoked in the VM class linking code.
*/
private
static
long
findNative
(
ClassLoader
loader
,
String
entryName
)
{
Map
<
String
,
NativeLibrary
>
libs
=
loader
!=
null
?
loader
.
nativeLibraries
()
:
systemNativeLibraries
();
if
(
libs
.
isEmpty
())
return
0
;
// the native libraries map may be updated in another thread
// when a native library is being loaded. No symbol will be
// searched from it yet.
for
(
NativeLibrary
lib
:
libs
.
values
())
{
long
entry
=
lib
.
findEntry
(
entryName
);
if
(
entry
!=
0
)
return
entry
;
}
return
0
;
}
// All native library names we've loaded.
// This also serves as the lock to obtain nativeLibraries
// and write to nativeLibraryContext.
private
static
final
Set
<
String
>
loadedLibraryNames
=
new
HashSet
<>();
// Native libraries belonging to system classes.
private
static
volatile
Map
<
String
,
NativeLibrary
>
systemNativeLibraries
;
// Native libraries associated with the class loader.
private
volatile
Map
<
String
,
NativeLibrary
>
nativeLibraries
;
/*
* Returns the native libraries map associated with bootstrap class loader
* This method will create the map at the first time when called.
*/
private
static
Map
<
String
,
NativeLibrary
>
systemNativeLibraries
()
{
Map
<
String
,
NativeLibrary
>
libs
=
systemNativeLibraries
;
if
(
libs
==
null
)
{
synchronized
(
loadedLibraryNames
)
{
if
(
loadedLibraryNames
.
contains
(
name
))
{
throw
new
UnsatisfiedLinkError
(
"Native Library "
+
name
+
" already loaded in another classloader"
);
libs
=
systemNativeLibraries
;
if
(
libs
==
null
)
{
libs
=
systemNativeLibraries
=
new
ConcurrentHashMap
<>();
}
/* If the library is being loaded (must be by the same thread,
* because Runtime.load and Runtime.loadLibrary are
* synchronous). The reason is can occur is that the JNI_OnLoad
* function can cause another loadLibrary invocation.
*
* Thus we can use a static stack to hold the list of libraries
* we are loading.
*
* If there is a pending load operation for the library, we
* immediately return success; otherwise, we raise
* UnsatisfiedLinkError.
*/
int
n
=
nativeLibraryContext
.
size
();
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
NativeLibrary
lib
=
nativeLibraryContext
.
elementAt
(
i
);
if
(
name
.
equals
(
lib
.
name
))
{
if
(
loader
==
lib
.
fromClass
.
getClassLoader
())
{
return
true
;
}
else
{
throw
new
UnsatisfiedLinkError
(
"Native Library "
+
name
+
" is being loaded in another classloader"
);
}
}
}
NativeLibrary
lib
=
new
NativeLibrary
(
fromClass
,
name
,
isBuiltin
);
nativeLibraryContext
.
push
(
lib
);
try
{
lib
.
load
(
name
,
isBuiltin
);
}
finally
{
nativeLibraryContext
.
pop
();
}
if
(
lib
.
loaded
)
{
loadedLibraryNames
.
addElement
(
name
);
libs
.
addElement
(
lib
);
return
true
;
}
return
false
;
}
}
return
libs
;
}
// Invoked in the VM class linking code.
static
long
findNative
(
ClassLoader
loader
,
String
name
)
{
Vector
<
NativeLibrary
>
libs
=
loader
!=
null
?
loader
.
nativeLibraries
:
systemNativeLibraries
;
synchronized
(
libs
)
{
int
size
=
libs
.
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
NativeLibrary
lib
=
libs
.
elementAt
(
i
);
long
entry
=
lib
.
find
(
name
);
if
(
entry
!=
0
)
return
entry
;
/*
* Returns the native libraries map associated with this class loader
* This method will create the map at the first time when called.
*/
private
Map
<
String
,
NativeLibrary
>
nativeLibraries
()
{
Map
<
String
,
NativeLibrary
>
libs
=
nativeLibraries
;
if
(
libs
==
null
)
{
synchronized
(
loadedLibraryNames
)
{
libs
=
nativeLibraries
;
if
(
libs
==
null
)
{
libs
=
nativeLibraries
=
new
ConcurrentHashMap
<>();
}
}
}
return
0
;
return
libs
;
}
// -- Assertion management --
final
Object
assertionLock
;
...
...
src/java.base/share/classes/java/lang/Runtime.java
浏览文件 @
d39a295f
...
...
@@ -765,7 +765,9 @@ public class Runtime {
* with the VM, then the JNI_OnLoad_L function exported by the library
* is invoked rather than attempting to load a dynamic library.
* A filename matching the argument does not have to exist in the file
* system. See the JNI Specification for more details.
* system.
* See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
* for more details.
*
* Otherwise, the filename argument is mapped to a native library image in
* an implementation-dependent manner.
...
...
@@ -818,7 +820,8 @@ public class Runtime {
* specific prefix, file extension or path. If a native library
* called {@code libname} is statically linked with the VM, then the
* JNI_OnLoad_{@code libname} function exported by the library is invoked.
* See the JNI Specification for more details.
* See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
* for more details.
*
* Otherwise, the libname argument is loaded from a system library
* location and mapped to a native library image in an implementation-
...
...
src/java.base/share/classes/java/lang/System.java
浏览文件 @
d39a295f
...
...
@@ -1799,7 +1799,8 @@ public final class System {
* is invoked rather than attempting to load a dynamic library.
* A filename matching the argument does not have to exist in the
* file system.
* See the JNI Specification for more details.
* See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
* for more details.
*
* Otherwise, the filename argument is mapped to a native library image in
* an implementation-dependent manner.
...
...
@@ -1835,7 +1836,8 @@ public final class System {
* specific prefix, file extension or path. If a native library
* called <code>libname</code> is statically linked with the VM, then the
* JNI_OnLoad_<code>libname</code> function exported by the library is invoked.
* See the JNI Specification for more details.
* See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
* for more details.
*
* Otherwise, the libname argument is loaded from a system library
* location and mapped to a native library image in an implementation-
...
...
src/java.base/share/native/libjava/ClassLoader.c
浏览文件 @
d39a295f
...
...
@@ -260,7 +260,6 @@ Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader,
static
jfieldID
handleID
;
static
jfieldID
jniVersionID
;
static
jfieldID
loadedID
;
static
void
*
procHandle
;
static
jboolean
initIDs
(
JNIEnv
*
env
)
...
...
@@ -276,9 +275,6 @@ static jboolean initIDs(JNIEnv *env)
jniVersionID
=
(
*
env
)
->
GetFieldID
(
env
,
this
,
"jniVersion"
,
"I"
);
if
(
jniVersionID
==
0
)
return
JNI_FALSE
;
loadedID
=
(
*
env
)
->
GetFieldID
(
env
,
this
,
"loaded"
,
"Z"
);
if
(
loadedID
==
0
)
return
JNI_FALSE
;
procHandle
=
getProcessHandle
();
}
return
JNI_TRUE
;
...
...
@@ -335,30 +331,31 @@ static void *findJniFunction(JNIEnv *env, void *handle,
/*
* Class: java_lang_ClassLoader_NativeLibrary
* Method: load
* Signature: (Ljava/lang/String;Z)
V
* Method: load
0
* Signature: (Ljava/lang/String;Z)
Z
*/
JNIEXPORT
void
JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_load
JNIEXPORT
jboolean
JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_load
0
(
JNIEnv
*
env
,
jobject
this
,
jstring
name
,
jboolean
isBuiltin
)
{
const
char
*
cname
;
jint
jniVersion
;
jthrowable
cause
;
void
*
handle
;
jboolean
loaded
=
JNI_FALSE
;
if
(
!
initIDs
(
env
))
return
;
return
JNI_FALSE
;
cname
=
JNU_GetStringPlatformChars
(
env
,
name
,
0
);
if
(
cname
==
0
)
return
;
return
JNI_FALSE
;
handle
=
isBuiltin
?
procHandle
:
JVM_LoadLibrary
(
cname
);
if
(
handle
)
{
JNI_OnLoad_t
JNI_OnLoad
;
JNI_OnLoad
=
(
JNI_OnLoad_t
)
findJniFunction
(
env
,
handle
,
isBuiltin
?
cname
:
NULL
,
JNI_TRUE
);
isBuiltin
?
cname
:
NULL
,
JNI_TRUE
);
if
(
JNI_OnLoad
)
{
JavaVM
*
jvm
;
(
*
env
)
->
GetJavaVM
(
env
,
&
jvm
);
...
...
@@ -400,20 +397,21 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load
goto
done
;
}
(
*
env
)
->
SetLongField
(
env
,
this
,
handleID
,
ptr_to_jlong
(
handle
));
(
*
env
)
->
SetBooleanField
(
env
,
this
,
loadedID
,
JNI_TRUE
)
;
loaded
=
JNI_TRUE
;
done:
JNU_ReleaseStringPlatformChars
(
env
,
name
,
cname
);
return
loaded
;
}
/*
* Class: java_lang_ClassLoader_NativeLibrary
* Method: unload
* Signature: (
Z
)V
* Signature: (
Ljava/lang/String;ZJ
)V
*/
JNIEXPORT
void
JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_unload
(
JNIEnv
*
env
,
j
object
this
,
jstring
name
,
jboolean
isBuiltin
)
(
JNIEnv
*
env
,
j
class
cls
,
jstring
name
,
jboolean
isBuiltin
,
jlong
address
)
{
const
char
*
onUnloadSymbols
[]
=
JNI_ONUNLOAD_SYMBOLS
;
void
*
handle
;
...
...
@@ -426,10 +424,10 @@ Java_java_lang_ClassLoader_00024NativeLibrary_unload
if
(
cname
==
NULL
)
{
return
;
}
handle
=
jlong_to_ptr
(
(
*
env
)
->
GetLongField
(
env
,
this
,
handleID
)
);
handle
=
jlong_to_ptr
(
address
);
JNI_OnUnload
=
(
JNI_OnUnload_t
)
findJniFunction
(
env
,
handle
,
isBuiltin
?
cname
:
NULL
,
JNI_FALSE
);
isBuiltin
?
cname
:
NULL
,
JNI_FALSE
);
if
(
JNI_OnUnload
)
{
JavaVM
*
jvm
;
(
*
env
)
->
GetJavaVM
(
env
,
&
jvm
);
...
...
@@ -443,11 +441,11 @@ Java_java_lang_ClassLoader_00024NativeLibrary_unload
/*
* Class: java_lang_ClassLoader_NativeLibrary
* Method: find
* Method: find
Entry
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT
jlong
JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_find
Java_java_lang_ClassLoader_00024NativeLibrary_find
Entry
(
JNIEnv
*
env
,
jobject
this
,
jstring
name
)
{
jlong
handle
;
...
...
test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java
0 → 100644
浏览文件 @
d39a295f
/*
* Copyright (c) 2017, 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.
*/
/*
* @test
* @bug 8164512
* @summary verify if the native library is unloaded when the class loader is GC'ed
* @build p.Test
* @run main/othervm/native -Xcheck:jni NativeLibraryTest
*/
import
java.io.IOException
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.net.URLClassLoader
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
public
class
NativeLibraryTest
{
static
final
Path
CLASSES
=
Paths
.
get
(
"classes"
);
static
int
unloadedCount
=
0
;
/*
* Called by JNI_OnUnload when the native library is unloaded
*/
static
void
nativeLibraryUnloaded
()
{
unloadedCount
++;
}
public
static
void
main
(
String
...
args
)
throws
Exception
{
setup
();
for
(
int
count
=
1
;
count
<=
5
;
count
++)
{
// create a class loader and load a native library
runTest
();
// unloading the class loader and native library
System
.
gc
();
// give Cleaner thread a chance to unload the native library
Thread
.
sleep
(
100
);
// unloadedCount is incremented when the native library is unloaded
if
(
count
!=
unloadedCount
)
{
throw
new
RuntimeException
(
"Expected unloaded="
+
count
+
" but got="
+
unloadedCount
);
}
}
}
/*
* Loads p.Test class with a new class loader and its static initializer
* will load a native library.
*
* The class loader becomes unreachable when this method returns and
* the native library should be unloaded at some point after the class
* loader is garbage collected.
*/
static
void
runTest
()
throws
Exception
{
// invoke p.Test.run() that loads the native library
Runnable
r
=
newTestRunnable
();
r
.
run
();
// reload the native library by the same class loader
r
.
run
();
// load the native library by another class loader
Runnable
r1
=
newTestRunnable
();
try
{
r1
.
run
();
throw
new
RuntimeException
(
"should fail to load the native library"
+
" by another class loader"
);
}
catch
(
UnsatisfiedLinkError
e
)
{}
}
/*
* Loads p.Test class with a new class loader and returns
* a Runnable instance.
*/
static
Runnable
newTestRunnable
()
throws
Exception
{
TestLoader
loader
=
new
TestLoader
();
Class
<?>
c
=
Class
.
forName
(
"p.Test"
,
true
,
loader
);
return
(
Runnable
)
c
.
newInstance
();
}
static
class
TestLoader
extends
URLClassLoader
{
static
URL
[]
toURLs
()
{
try
{
return
new
URL
[]
{
CLASSES
.
toUri
().
toURL
()
};
}
catch
(
MalformedURLException
e
)
{
throw
new
Error
(
e
);
}
}
TestLoader
()
{
super
(
"testloader"
,
toURLs
(),
ClassLoader
.
getSystemClassLoader
());
}
}
/*
* move p/Test.class out from classpath to the scratch directory
*/
static
void
setup
()
throws
IOException
{
String
dir
=
System
.
getProperty
(
"test.classes"
,
"."
);
Path
file
=
Paths
.
get
(
"p"
,
"Test.class"
);
Files
.
createDirectories
(
CLASSES
.
resolve
(
"p"
));
Files
.
move
(
Paths
.
get
(
dir
).
resolve
(
file
),
CLASSES
.
resolve
(
"p"
).
resolve
(
"Test.class"
));
}
}
test/jdk/java/lang/ClassLoader/nativeLibrary/libnativeLibraryTest.c
0 → 100644
浏览文件 @
d39a295f
/*
* Copyright (c) 2017, 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include "jni.h"
#include "jni_util.h"
static
jint
count
=
0
;
static
jclass
test_class
;
static
jint
current_jni_version
=
JNI_VERSION_10
;
JNIEXPORT
jint
JNICALL
JNI_OnLoad
(
JavaVM
*
vm
,
void
*
reserved
)
{
JNIEnv
*
env
;
jclass
cl
;
(
*
vm
)
->
GetEnv
(
vm
,
(
void
**
)
&
env
,
current_jni_version
);
cl
=
(
*
env
)
->
FindClass
(
env
,
"NativeLibraryTest"
);
test_class
=
(
*
env
)
->
NewGlobalRef
(
env
,
cl
);
// increment the count when JNI_OnLoad is called
count
++
;
return
current_jni_version
;
}
JNIEXPORT
void
JNICALL
JNI_OnUnload
(
JavaVM
*
vm
,
void
*
reserved
)
{
JNIEnv
*
env
;
jmethodID
mid
;
jclass
cl
;
(
*
vm
)
->
GetEnv
(
vm
,
(
void
**
)
&
env
,
current_jni_version
);
mid
=
(
*
env
)
->
GetStaticMethodID
(
env
,
test_class
,
"nativeLibraryUnloaded"
,
"()V"
);
(
*
env
)
->
CallStaticVoidMethod
(
env
,
test_class
,
mid
);
if
((
*
env
)
->
ExceptionCheck
(
env
))
{
(
*
env
)
->
ExceptionDescribe
(
env
);
(
*
env
)
->
FatalError
(
env
,
"Exception thrown"
);
}
cl
=
(
*
env
)
->
FindClass
(
env
,
"p/Test"
);
if
(
cl
!=
NULL
)
{
(
*
env
)
->
FatalError
(
env
,
"p/Test class should not be found"
);
}
}
JNIEXPORT
jint
JNICALL
Java_p_Test_count
(
JNIEnv
*
env
,
jclass
cls
)
{
return
count
;
}
test/jdk/java/lang/ClassLoader/nativeLibrary/p/Test.java
0 → 100644
浏览文件 @
d39a295f
/*
* Copyright (c) 2017, 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.
*/
package
p
;
public
class
Test
implements
Runnable
{
public
static
native
int
count
();
/**
* Tests if the native library is loaded.
*/
public
void
run
()
{
System
.
loadLibrary
(
"nativeLibraryTest"
);
if
(
count
()
!=
1
)
{
throw
new
RuntimeException
(
"Expected count = 1 but got "
+
count
());
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录