Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
01f9442d
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
01f9442d
编写于
12月 25, 2017
作者:
D
dbuck
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8044107: Add Diagnostic Command to list all ClassLoaders
Reviewed-by: dholmes
上级
621b19d4
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
491 addition
and
0 deletion
+491
-0
src/share/vm/classfile/classLoaderStats.cpp
src/share/vm/classfile/classLoaderStats.cpp
+167
-0
src/share/vm/classfile/classLoaderStats.hpp
src/share/vm/classfile/classLoaderStats.hpp
+152
-0
src/share/vm/memory/metaspace.cpp
src/share/vm/memory/metaspace.cpp
+11
-0
src/share/vm/memory/metaspace.hpp
src/share/vm/memory/metaspace.hpp
+3
-0
src/share/vm/runtime/vm_operations.hpp
src/share/vm/runtime/vm_operations.hpp
+1
-0
src/share/vm/services/diagnosticCommand.cpp
src/share/vm/services/diagnosticCommand.cpp
+2
-0
test/serviceability/dcmd/ClassLoaderStatsTest.java
test/serviceability/dcmd/ClassLoaderStatsTest.java
+155
-0
未找到文件。
src/share/vm/classfile/classLoaderStats.cpp
0 → 100644
浏览文件 @
01f9442d
/*
* Copyright (c) 2014, 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 "precompiled.hpp"
#include "classfile/classLoaderStats.hpp"
#include "utilities/globalDefinitions.hpp"
class
ClassStatsClosure
:
public
KlassClosure
{
public:
int
_num_classes
;
ClassStatsClosure
()
:
_num_classes
(
0
)
{
}
virtual
void
do_klass
(
Klass
*
k
)
{
_num_classes
++
;
}
};
void
ClassLoaderStatsClosure
::
do_cld
(
ClassLoaderData
*
cld
)
{
oop
cl
=
cld
->
class_loader
();
ClassLoaderStats
*
cls
;
// The hashtable key is the ClassLoader oop since we want to account
// for "real" classes and anonymous classes together
ClassLoaderStats
**
cls_ptr
=
_stats
->
get
(
cl
);
if
(
cls_ptr
==
NULL
)
{
cls
=
new
ClassLoaderStats
();
_stats
->
put
(
cl
,
cls
);
_total_loaders
++
;
}
else
{
cls
=
*
cls_ptr
;
}
if
(
!
cld
->
is_anonymous
())
{
cls
->
_cld
=
cld
;
}
cls
->
_class_loader
=
cl
;
if
(
cl
!=
NULL
)
{
cls
->
_parent
=
java_lang_ClassLoader
::
parent
(
cl
);
addEmptyParents
(
cls
->
_parent
);
}
ClassStatsClosure
csc
;
cld
->
classes_do
(
&
csc
);
if
(
cld
->
is_anonymous
())
{
cls
->
_anon_classes_count
+=
csc
.
_num_classes
;
}
else
{
cls
->
_classes_count
=
csc
.
_num_classes
;
}
_total_classes
+=
csc
.
_num_classes
;
Metaspace
*
ms
=
cld
->
metaspace_or_null
();
if
(
ms
!=
NULL
)
{
if
(
cld
->
is_anonymous
())
{
cls
->
_anon_chunk_sz
+=
ms
->
allocated_chunks_bytes
();
cls
->
_anon_block_sz
+=
ms
->
allocated_blocks_bytes
();
}
else
{
cls
->
_chunk_sz
=
ms
->
allocated_chunks_bytes
();
cls
->
_block_sz
=
ms
->
allocated_blocks_bytes
();
}
_total_chunk_sz
+=
ms
->
allocated_chunks_bytes
();
_total_block_sz
+=
ms
->
allocated_blocks_bytes
();
}
}
// Handles the difference in pointer width on 32 and 64 bit platforms
#ifdef _LP64
#define SPACE "%8s"
#else
#define SPACE "%s"
#endif
bool
ClassLoaderStatsClosure
::
do_entry
(
oop
const
&
key
,
ClassLoaderStats
*
const
&
cls
)
{
Klass
*
class_loader_klass
=
(
cls
->
_class_loader
==
NULL
?
NULL
:
cls
->
_class_loader
->
klass
());
Klass
*
parent_klass
=
(
cls
->
_parent
==
NULL
?
NULL
:
cls
->
_parent
->
klass
());
_out
->
print
(
INTPTR_FORMAT
" "
INTPTR_FORMAT
" "
INTPTR_FORMAT
" "
UINTX_FORMAT_W
(
6
)
" "
SIZE_FORMAT_W
(
8
)
" "
SIZE_FORMAT_W
(
8
)
" "
,
p2i
(
class_loader_klass
),
p2i
(
parent_klass
),
p2i
(
cls
->
_cld
),
cls
->
_classes_count
,
cls
->
_chunk_sz
,
cls
->
_block_sz
);
if
(
class_loader_klass
!=
NULL
)
{
_out
->
print
(
"%s"
,
class_loader_klass
->
external_name
());
}
else
{
_out
->
print
(
"<boot class loader>"
);
}
_out
->
cr
();
if
(
cls
->
_anon_classes_count
>
0
)
{
_out
->
print_cr
(
SPACE
SPACE
SPACE
" "
UINTX_FORMAT_W
(
6
)
" "
SIZE_FORMAT_W
(
8
)
" "
SIZE_FORMAT_W
(
8
)
" + unsafe anonymous classes"
,
""
,
""
,
""
,
cls
->
_anon_classes_count
,
cls
->
_anon_chunk_sz
,
cls
->
_anon_block_sz
);
}
return
true
;
}
void
ClassLoaderStatsClosure
::
print
()
{
_out
->
print_cr
(
"ClassLoader"
SPACE
" Parent"
SPACE
" CLD*"
SPACE
" Classes ChunkSz BlockSz Type"
,
""
,
""
,
""
);
_stats
->
iterate
(
this
);
_out
->
print
(
"Total = "
UINTX_FORMAT_W
(
-
6
),
_total_loaders
);
_out
->
print
(
SPACE
SPACE
SPACE
" "
,
""
,
""
,
""
);
_out
->
print_cr
(
UINTX_FORMAT_W
(
6
)
" "
SIZE_FORMAT_W
(
8
)
" "
SIZE_FORMAT_W
(
8
)
" "
,
_total_classes
,
_total_chunk_sz
,
_total_block_sz
);
_out
->
print_cr
(
"ChunkSz: Total size of all allocated metaspace chunks"
);
_out
->
print_cr
(
"BlockSz: Total size of all allocated metaspace blocks (each chunk has several blocks)"
);
}
void
ClassLoaderStatsClosure
::
addEmptyParents
(
oop
cl
)
{
while
(
cl
!=
NULL
&&
java_lang_ClassLoader
::
loader_data
(
cl
)
==
NULL
)
{
// This classloader has not loaded any classes
ClassLoaderStats
**
cls_ptr
=
_stats
->
get
(
cl
);
if
(
cls_ptr
==
NULL
)
{
// It does not exist in our table - add it
ClassLoaderStats
*
cls
=
new
ClassLoaderStats
();
cls
->
_class_loader
=
cl
;
cls
->
_parent
=
java_lang_ClassLoader
::
parent
(
cl
);
_stats
->
put
(
cl
,
cls
);
_total_loaders
++
;
}
cl
=
java_lang_ClassLoader
::
parent
(
cl
);
}
}
void
ClassLoaderStatsVMOperation
::
doit
()
{
ClassLoaderStatsClosure
clsc
(
_out
);
ClassLoaderDataGraph
::
cld_do
(
&
clsc
);
clsc
.
print
();
}
void
ClassLoaderStatsDCmd
::
execute
(
DCmdSource
source
,
TRAPS
)
{
ClassLoaderStatsVMOperation
op
(
output
());
VMThread
::
execute
(
&
op
);
}
src/share/vm/classfile/classLoaderStats.hpp
0 → 100644
浏览文件 @
01f9442d
/*
* Copyright (c) 2014, 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.
*
*/
#ifndef SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP
#include "classfile/classLoaderData.hpp"
#include "oops/klass.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/vm_operations.hpp"
#include "services/diagnosticCommand.hpp"
#include "utilities/resourceHash.hpp"
class
ClassLoaderStatsDCmd
:
public
DCmd
{
public:
ClassLoaderStatsDCmd
(
outputStream
*
output
,
bool
heap
)
:
DCmd
(
output
,
heap
)
{
}
static
const
char
*
name
()
{
return
"VM.classloader_stats"
;
}
static
const
char
*
description
()
{
return
"Print statistics about all ClassLoaders."
;
}
static
const
char
*
impact
()
{
return
"Low"
;
}
virtual
void
execute
(
DCmdSource
source
,
TRAPS
);
static
int
num_arguments
()
{
return
0
;
}
static
const
JavaPermission
permission
()
{
JavaPermission
p
=
{
"java.lang.management.ManagementPermission"
,
"monitor"
,
NULL
};
return
p
;
}
};
class
ClassLoaderStats
:
public
ResourceObj
{
public:
ClassLoaderData
*
_cld
;
oop
_class_loader
;
oop
_parent
;
size_t
_chunk_sz
;
size_t
_block_sz
;
uintx
_classes_count
;
size_t
_anon_chunk_sz
;
size_t
_anon_block_sz
;
uintx
_anon_classes_count
;
ClassLoaderStats
()
:
_cld
(
0
),
_class_loader
(
0
),
_parent
(
0
),
_chunk_sz
(
0
),
_block_sz
(
0
),
_classes_count
(
0
),
_anon_block_sz
(
0
),
_anon_chunk_sz
(
0
),
_anon_classes_count
(
0
)
{
}
};
class
ClassLoaderStatsClosure
:
public
CLDClosure
{
protected:
static
bool
oop_equals
(
oop
const
&
s1
,
oop
const
&
s2
)
{
return
s1
==
s2
;
}
static
unsigned
oop_hash
(
oop
const
&
s1
)
{
unsigned
hash
=
(
unsigned
)((
uintptr_t
)
&
s1
);
return
hash
^
(
hash
>>
LogMinObjAlignment
);
}
typedef
ResourceHashtable
<
oop
,
ClassLoaderStats
*
,
ClassLoaderStatsClosure
::
oop_hash
,
ClassLoaderStatsClosure
::
oop_equals
>
StatsTable
;
outputStream
*
_out
;
StatsTable
*
_stats
;
uintx
_total_loaders
;
uintx
_total_classes
;
size_t
_total_chunk_sz
;
size_t
_total_block_sz
;
public:
ClassLoaderStatsClosure
(
outputStream
*
out
)
:
_out
(
out
),
_total_loaders
(
0
),
_total_block_sz
(
0
),
_total_chunk_sz
(
0
),
_total_classes
(
0
),
_stats
(
new
StatsTable
())
{
}
virtual
void
do_cld
(
ClassLoaderData
*
cld
);
virtual
bool
do_entry
(
oop
const
&
key
,
ClassLoaderStats
*
const
&
cls
);
void
print
();
private:
void
addEmptyParents
(
oop
cl
);
};
class
ClassLoaderStatsVMOperation
:
public
VM_Operation
{
outputStream
*
_out
;
public:
ClassLoaderStatsVMOperation
(
outputStream
*
out
)
:
_out
(
out
)
{
}
VMOp_Type
type
()
const
{
return
VMOp_ClassLoaderStatsOperation
;
}
void
doit
();
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP
src/share/vm/memory/metaspace.cpp
浏览文件 @
01f9442d
...
...
@@ -706,6 +706,7 @@ class SpaceManager : public CHeapObj<mtClass> {
size_t
allocated_blocks_words
()
const
{
return
_allocated_blocks_words
;
}
size_t
allocated_blocks_bytes
()
const
{
return
_allocated_blocks_words
*
BytesPerWord
;
}
size_t
allocated_chunks_words
()
const
{
return
_allocated_chunks_words
;
}
size_t
allocated_chunks_bytes
()
const
{
return
_allocated_chunks_words
*
BytesPerWord
;
}
size_t
allocated_chunks_count
()
const
{
return
_allocated_chunks_count
;
}
bool
is_humongous
(
size_t
word_size
)
{
return
word_size
>
medium_chunk_size
();
}
...
...
@@ -3463,6 +3464,16 @@ size_t Metaspace::capacity_bytes_slow(MetadataType mdtype) const {
return
capacity_words_slow
(
mdtype
)
*
BytesPerWord
;
}
size_t
Metaspace
::
allocated_blocks_bytes
()
const
{
return
vsm
()
->
allocated_blocks_bytes
()
+
(
using_class_space
()
?
class_vsm
()
->
allocated_blocks_bytes
()
:
0
);
}
size_t
Metaspace
::
allocated_chunks_bytes
()
const
{
return
vsm
()
->
allocated_chunks_bytes
()
+
(
using_class_space
()
?
class_vsm
()
->
allocated_chunks_bytes
()
:
0
);
}
void
Metaspace
::
deallocate
(
MetaWord
*
ptr
,
size_t
word_size
,
bool
is_class
)
{
if
(
SafepointSynchronize
::
is_at_safepoint
())
{
if
(
DumpSharedSpaces
&&
PrintSharedSpaces
)
{
...
...
src/share/vm/memory/metaspace.hpp
浏览文件 @
01f9442d
...
...
@@ -232,6 +232,9 @@ class Metaspace : public CHeapObj<mtClass> {
size_t
used_bytes_slow
(
MetadataType
mdtype
)
const
;
size_t
capacity_bytes_slow
(
MetadataType
mdtype
)
const
;
size_t
allocated_blocks_bytes
()
const
;
size_t
allocated_chunks_bytes
()
const
;
static
MetaWord
*
allocate
(
ClassLoaderData
*
loader_data
,
size_t
word_size
,
bool
read_only
,
MetaspaceObj
::
Type
type
,
TRAPS
);
void
deallocate
(
MetaWord
*
ptr
,
size_t
byte_size
,
bool
is_class
);
...
...
src/share/vm/runtime/vm_operations.hpp
浏览文件 @
01f9442d
...
...
@@ -97,6 +97,7 @@
template(LinuxDllLoad) \
template(RotateGCLog) \
template(WhiteBoxOperation) \
template(ClassLoaderStatsOperation) \
class
VM_Operation
:
public
CHeapObj
<
mtInternal
>
{
public:
...
...
src/share/vm/services/diagnosticCommand.cpp
浏览文件 @
01f9442d
...
...
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderStats.hpp"
#include "gc_implementation/shared/vmGCOperations.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.hpp"
...
...
@@ -61,6 +62,7 @@ void DCmdRegistrant::register_dcmds(){
#endif // INCLUDE_SERVICES
DCmdFactory
::
register_DCmdFactory
(
new
DCmdFactoryImpl
<
ThreadDumpDCmd
>
(
full_export
,
true
,
false
));
DCmdFactory
::
register_DCmdFactory
(
new
DCmdFactoryImpl
<
RotateGCLogDCmd
>
(
full_export
,
true
,
false
));
DCmdFactory
::
register_DCmdFactory
(
new
DCmdFactoryImpl
<
ClassLoaderStatsDCmd
>
(
full_export
,
true
,
false
));
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
...
...
test/serviceability/dcmd/ClassLoaderStatsTest.java
0 → 100644
浏览文件 @
01f9442d
/*
* Copyright (c) 2014, 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
*
* @build ClassLoaderStatsTest DcmdUtil
* @run main ClassLoaderStatsTest
*/
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.StringReader
;
import
java.nio.ByteBuffer
;
import
java.nio.channels.FileChannel
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
public
class
ClassLoaderStatsTest
{
// ClassLoader Parent CLD* Classes ChunkSz BlockSz Type
// 0x00000007c0215928 0x0000000000000000 0x0000000000000000 0 0 0 org.eclipse.osgi.baseadaptor.BaseAdaptor$1
// 0x00000007c0009868 0x0000000000000000 0x00007fc52aebcc80 1 6144 3768 sun.reflect.DelegatingClassLoader
// 0x00000007c0009868 0x0000000000000000 0x00007fc52b8916d0 1 6144 3688 sun.reflect.DelegatingClassLoader
// 0x00000007c0009868 0x00000007c0038ba8 0x00007fc52afb8760 1 6144 3688 sun.reflect.DelegatingClassLoader
// 0x00000007c0009868 0x0000000000000000 0x00007fc52afbb1a0 1 6144 3688 sun.reflect.DelegatingClassLoader
// 0x0000000000000000 0x0000000000000000 0x00007fc523416070 5019 30060544 29956216 <boot classloader>
// 455 1210368 672848 + unsafe anonymous classes
// 0x00000007c016b5c8 0x00000007c0038ba8 0x00007fc52a995000 5 8192 5864 org.netbeans.StandardModule$OneModuleClassLoader
// 0x00000007c0009868 0x00000007c016b5c8 0x00007fc52ac13640 1 6144 3896 sun.reflect.DelegatingClassLoader
// ...
static
Pattern
clLine
=
Pattern
.
compile
(
"0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*(.*)"
);
static
Pattern
anonLine
=
Pattern
.
compile
(
"\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*.*"
);
public
static
DummyClassLoader
dummyloader
;
public
static
void
main
(
String
arg
[])
throws
Exception
{
// create a classloader and load our special class
dummyloader
=
new
DummyClassLoader
();
Class
<?>
c
=
Class
.
forName
(
"TestClass"
,
true
,
dummyloader
);
if
(
c
.
getClassLoader
()
!=
dummyloader
)
{
throw
new
RuntimeException
(
"TestClass defined by wrong classloader: "
+
c
.
getClassLoader
());
}
String
result
=
DcmdUtil
.
executeDcmd
(
"VM.classloader_stats"
);
BufferedReader
r
=
new
BufferedReader
(
new
StringReader
(
result
));
String
line
;
while
((
line
=
r
.
readLine
())
!=
null
)
{
Matcher
m
=
clLine
.
matcher
(
line
);
if
(
m
.
matches
())
{
// verify that DummyClassLoader has loaded 1 class and 1 anonymous class
if
(
m
.
group
(
4
).
equals
(
"ClassLoaderStatsTest$DummyClassLoader"
))
{
System
.
out
.
println
(
"line: "
+
line
);
if
(!
m
.
group
(
1
).
equals
(
"1"
))
{
throw
new
Exception
(
"Should have loaded 1 class: "
+
line
);
}
checkPositiveInt
(
m
.
group
(
2
));
checkPositiveInt
(
m
.
group
(
3
));
String
next
=
r
.
readLine
();
System
.
out
.
println
(
"next: "
+
next
);
Matcher
m1
=
anonLine
.
matcher
(
next
);
m1
.
matches
();
if
(!
m1
.
group
(
1
).
equals
(
"1"
))
{
throw
new
Exception
(
"Should have loaded 1 anonymous class, but found : "
+
m1
.
group
(
1
));
}
checkPositiveInt
(
m1
.
group
(
2
));
checkPositiveInt
(
m1
.
group
(
3
));
}
}
}
}
private
static
void
checkPositiveInt
(
String
s
)
throws
Exception
{
if
(
Integer
.
parseInt
(
s
)
<=
0
)
{
throw
new
Exception
(
"Value should have been > 0: "
+
s
);
}
}
public
static
class
DummyClassLoader
extends
ClassLoader
{
public
static
final
String
CLASS_NAME
=
"TestClass"
;
static
ByteBuffer
readClassFile
(
String
name
)
{
File
f
=
new
File
(
System
.
getProperty
(
"test.classes"
,
"."
),
name
);
try
(
FileInputStream
fin
=
new
FileInputStream
(
f
);
FileChannel
fc
=
fin
.
getChannel
())
{
return
fc
.
map
(
FileChannel
.
MapMode
.
READ_ONLY
,
0
,
fc
.
size
());
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
"Can't open file: "
+
name
,
e
);
}
}
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
Class
<?>
c
;
if
(!
"TestClass"
.
equals
(
name
))
{
c
=
super
.
loadClass
(
name
,
resolve
);
}
else
{
// should not delegate to the system class loader
c
=
findClass
(
name
);
if
(
resolve
)
{
resolveClass
(
c
);
}
}
return
c
;
}
protected
Class
<?>
findClass
(
String
name
)
throws
ClassNotFoundException
{
if
(!
"TestClass"
.
equals
(
name
))
{
throw
new
ClassNotFoundException
(
"Unexpected class: "
+
name
);
}
return
defineClass
(
name
,
readClassFile
(
name
+
".class"
),
null
);
}
}
/* DummyClassLoader */
}
class
TestClass
{
static
{
// force creation of anonymous class (for the lambdaform)
Runnable
r
=
()
->
System
.
out
.
println
(
"Hello"
);
r
.
run
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录