Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_langtools
提交
974e831f
D
dragonwell8_langtools
项目概览
openanolis
/
dragonwell8_langtools
通知
0
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_langtools
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
974e831f
编写于
12月 12, 2009
作者:
J
jjg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6907575: [classfile] add support for classfile dependency analysis
Reviewed-by: ksrini
上级
10e7c2c7
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
1135 addition
and
0 deletion
+1135
-0
src/share/classes/com/sun/tools/classfile/Dependencies.java
src/share/classes/com/sun/tools/classfile/Dependencies.java
+718
-0
src/share/classes/com/sun/tools/classfile/Dependency.java
src/share/classes/com/sun/tools/classfile/Dependency.java
+90
-0
test/tools/javap/classfile/deps/GetDeps.java
test/tools/javap/classfile/deps/GetDeps.java
+211
-0
test/tools/javap/classfile/deps/T6907575.java
test/tools/javap/classfile/deps/T6907575.java
+71
-0
test/tools/javap/classfile/deps/T6907575.out
test/tools/javap/classfile/deps/T6907575.out
+8
-0
test/tools/javap/classfile/deps/p/C1.java
test/tools/javap/classfile/deps/p/C1.java
+37
-0
未找到文件。
src/share/classes/com/sun/tools/classfile/Dependencies.java
0 → 100644
浏览文件 @
974e831f
/*
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
com.sun.tools.classfile
;
import
java.util.Deque
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.regex.Pattern
;
import
com.sun.tools.classfile.Dependency.Finder
;
import
com.sun.tools.classfile.Dependency.Filter
;
import
com.sun.tools.classfile.Dependency.Location
;
import
com.sun.tools.classfile.Type.ArrayType
;
import
com.sun.tools.classfile.Type.ClassSigType
;
import
com.sun.tools.classfile.Type.ClassType
;
import
com.sun.tools.classfile.Type.MethodType
;
import
com.sun.tools.classfile.Type.SimpleType
;
import
com.sun.tools.classfile.Type.TypeParamType
;
import
com.sun.tools.classfile.Type.WildcardType
;
import
static
com
.
sun
.
tools
.
classfile
.
ConstantPool
.*;
/**
* A framework for determining {@link Dependency dependencies} between class files.
*
* A {@link Dependency.Finder finder} is used to identify the dependencies of
* individual classes. Some finders may return subtypes of {@code Dependency} to
* further characterize the type of dependency, such as a dependency on a
* method within a class.
*
* A {@link Dependency.Filter filter} may be used to restrict the set of
* dependencies found by a finder.
*
* Dependencies that are found may be passed to a {@link Dependencies.Recorder
* recorder} so that the dependencies can be stored in a custom data structure.
*/
public
class
Dependencies
{
/**
* Thrown when a class file cannot be found.
*/
public
static
class
ClassFileNotFoundException
extends
Exception
{
private
static
final
long
serialVersionUID
=
3632265927794475048L
;
public
ClassFileNotFoundException
(
String
className
)
{
super
(
className
);
this
.
className
=
className
;
}
public
ClassFileNotFoundException
(
String
className
,
Throwable
cause
)
{
this
(
className
);
initCause
(
cause
);
}
public
final
String
className
;
}
/**
* Thrown when an exception is found processing a class file.
*/
public
static
class
ClassFileError
extends
Error
{
private
static
final
long
serialVersionUID
=
4111110813961313203L
;
public
ClassFileError
(
Throwable
cause
)
{
initCause
(
cause
);
}
}
/**
* Service provider interface to locate and read class files.
*/
public
interface
ClassFileReader
{
/**
* Get the ClassFile object for a specified class.
* @param className the name of the class to be returned.
* @return the ClassFile for the given class
* @throws Dependencies#ClassFileNotFoundException if the classfile cannot be
* found
*/
public
ClassFile
getClassFile
(
String
className
)
throws
ClassFileNotFoundException
;
}
/**
* Service provide interface to handle results.
*/
public
interface
Recorder
{
/**
* Record a dependency that has been found.
* @param d
*/
public
void
addDependency
(
Dependency
d
);
}
/**
* Get the default finder used to locate the dependencies for a class.
* @return the default finder
*/
public
static
Finder
getDefaultFinder
()
{
return
new
APIDependencyFinder
(
AccessFlags
.
ACC_PRIVATE
);
}
/**
* Get a finder used to locate the API dependencies for a class.
* These include the superclass, superinterfaces, and classes referenced in
* the declarations of fields and methods. The fields and methods that
* are checked can be limited according to a specified access.
* The access parameter must be one of {@link AccessFlags#ACC_PUBLIC ACC_PUBLIC},
* {@link AccessFlags#ACC_PRIVATE ACC_PRIVATE},
* {@link AccessFlags#ACC_PROTECTED ACC_PROTECTED}, or 0 for
* package private access. Members with greater than or equal accessibility
* to that specified will be searched for dependencies.
* @param access the access of members to be checked
* @return an API finder
*/
public
static
Finder
getAPIFinder
(
int
access
)
{
return
new
APIDependencyFinder
(
access
);
}
/**
* Get the finder used to locate the dependencies for a class.
* @return the finder
*/
public
Finder
getFinder
()
{
if
(
finder
==
null
)
finder
=
getDefaultFinder
();
return
finder
;
}
/**
* Set the finder used to locate the dependencies for a class.
* @param f the finder
*/
public
void
setFinder
(
Finder
f
)
{
f
.
getClass
();
// null check
finder
=
f
;
}
/**
* Get the default filter used to determine included when searching
* the transitive closure of all the dependencies.
* Unless overridden, the default filter accepts all dependencies.
* @return the default filter.
*/
public
static
Filter
getDefaultFilter
()
{
return
DefaultFilter
.
instance
();
}
/**
* Get a filter which uses a regular expression on the target's class name
* to determine if a dependency is of interest.
* @param pattern the pattern used to match the target's class name
* @return a filter for matching the target class name with a regular expression
*/
public
static
Filter
getRegexFilter
(
Pattern
pattern
)
{
return
new
TargetRegexFilter
(
pattern
);
}
/**
* Get a filter which checks the package of a target's class name
* to determine if a dependency is of interest. The filter checks if the
* package of the target's class matches any of a set of given package
* names. The match may optionally match subpackages of the given names as well.
* @param packageNames the package names used to match the target's class name
* @param matchSubpackages whether or not to match subpackages as well
* @return a filter for checking the target package name against a list of package names
*/
public
static
Filter
getPackageFilter
(
Set
<
String
>
packageNames
,
boolean
matchSubpackages
)
{
return
new
TargetPackageFilter
(
packageNames
,
matchSubpackages
);
}
/**
* Get the filter used to determine the dependencies included when searching
* the transitive closure of all the dependencies.
* Unless overridden, the default filter accepts all dependencies.
* @return the filter
*/
public
Filter
getFilter
()
{
if
(
filter
==
null
)
filter
=
getDefaultFilter
();
return
filter
;
}
/**
* Set the filter used to determine the dependencies included when searching
* the transitive closure of all the dependencies.
* @param f the filter
*/
public
void
setFilter
(
Filter
f
)
{
f
.
getClass
();
// null check
filter
=
f
;
}
/**
* Find the dependencies of a class, using the current
* {@link Dependencies#getFinder finder} and
* {@link Dependencies#getFilter filter}.
* The search may optionally include the transitive closure of all the
* filtered dependencies, by also searching in the classes named in those
* dependencies.
* @param classFinder a finder to locate class files
* @param rootClassNames the names of the root classes from which to begin
* searching
* @param transitiveClosure whether or not to also search those classes
* named in any filtered dependencies that are found.
* @return the set of dependencies that were found
* @throws ClassFileNotFoundException if a required class file cannot be found
* @throws ClassFileError if an error occurs while processing a class file,
* such as an error in the internal class file structure.
*/
public
Set
<
Dependency
>
findAllDependencies
(
ClassFileReader
classFinder
,
Set
<
String
>
rootClassNames
,
boolean
transitiveClosure
)
throws
ClassFileNotFoundException
{
final
Set
<
Dependency
>
results
=
new
HashSet
<
Dependency
>();
Recorder
r
=
new
Recorder
()
{
public
void
addDependency
(
Dependency
d
)
{
results
.
add
(
d
);
}
};
findAllDependencies
(
classFinder
,
rootClassNames
,
transitiveClosure
,
r
);
return
results
;
}
/**
* Find the dependencies of a class, using the current
* {@link Dependencies#getFinder finder} and
* {@link Dependencies#getFilter filter}.
* The search may optionally include the transitive closure of all the
* filtered dependencies, by also searching in the classes named in those
* dependencies.
* @param classFinder a finder to locate class files
* @param rootClassNames the names of the root classes from which to begin
* searching
* @param transitiveClosure whether or not to also search those classes
* named in any filtered dependencies that are found.
* @param recorder a recorder for handling the results
* @throws ClassFileNotFoundException if a required class file cannot be found
* @throws ClassFileError if an error occurs while processing a class file,
* such as an error in the internal class file structure.
*/
public
void
findAllDependencies
(
ClassFileReader
classFinder
,
Set
<
String
>
rootClassNames
,
boolean
transitiveClosure
,
Recorder
recorder
)
throws
ClassFileNotFoundException
{
Set
<
String
>
doneClasses
=
new
HashSet
<
String
>();
getFinder
();
// ensure initialized
getFilter
();
// ensure initialized
// Work queue of names of classfiles to be searched.
// Entries will be unique, and for classes that do not yet have
// dependencies in the results map.
Deque
<
String
>
deque
=
new
LinkedList
<
String
>(
rootClassNames
);
String
className
;
while
((
className
=
deque
.
poll
())
!=
null
)
{
assert
(!
doneClasses
.
contains
(
className
));
doneClasses
.
add
(
className
);
ClassFile
cf
=
classFinder
.
getClassFile
(
className
);
// The following code just applies the filter to the dependencies
// followed for the transitive closure.
for
(
Dependency
d:
finder
.
findDependencies
(
cf
))
{
recorder
.
addDependency
(
d
);
if
(
transitiveClosure
&&
filter
.
accepts
(
d
))
{
String
cn
=
d
.
getTarget
().
getClassName
();
if
(!
doneClasses
.
contains
(
cn
))
deque
.
add
(
cn
);
}
}
}
}
private
Filter
filter
;
private
Finder
finder
;
/**
* A location identifying a class.
*/
static
class
SimpleLocation
implements
Location
{
public
SimpleLocation
(
String
className
)
{
this
.
className
=
className
;
}
/**
* Get the name of the class being depended on. This name will be used to
* locate the class file for transitive dependency analysis.
* @return the name of the class being depended on
*/
public
String
getClassName
()
{
return
className
;
}
@Override
public
boolean
equals
(
Object
other
)
{
if
(
this
==
other
)
return
true
;
if
(!(
other
instanceof
SimpleLocation
))
return
false
;
return
(
className
.
equals
(((
SimpleLocation
)
other
).
className
));
}
@Override
public
int
hashCode
()
{
return
className
.
hashCode
();
}
@Override
public
String
toString
()
{
return
className
;
}
private
String
className
;
}
/**
* A dependency of one class on another.
*/
static
class
SimpleDependency
implements
Dependency
{
public
SimpleDependency
(
Location
origin
,
Location
target
)
{
this
.
origin
=
origin
;
this
.
target
=
target
;
}
public
Location
getOrigin
()
{
return
origin
;
}
public
Location
getTarget
()
{
return
target
;
}
@Override
public
boolean
equals
(
Object
other
)
{
if
(
this
==
other
)
return
true
;
if
(!(
other
instanceof
SimpleDependency
))
return
false
;
SimpleDependency
o
=
(
SimpleDependency
)
other
;
return
(
origin
.
equals
(
o
.
origin
)
&&
target
.
equals
(
o
.
target
));
}
@Override
public
int
hashCode
()
{
return
origin
.
hashCode
()
*
31
+
target
.
hashCode
();
}
@Override
public
String
toString
()
{
return
origin
+
":"
+
target
;
}
private
Location
origin
;
private
Location
target
;
}
/**
* This class accepts all dependencies.
*/
static
class
DefaultFilter
implements
Filter
{
private
static
DefaultFilter
instance
;
static
DefaultFilter
instance
()
{
if
(
instance
==
null
)
instance
=
new
DefaultFilter
();
return
instance
;
}
public
boolean
accepts
(
Dependency
dependency
)
{
return
true
;
}
}
/**
* This class accepts those dependencies whose target's class name matches a
* regular expression.
*/
static
class
TargetRegexFilter
implements
Filter
{
TargetRegexFilter
(
Pattern
pattern
)
{
this
.
pattern
=
pattern
;
}
public
boolean
accepts
(
Dependency
dependency
)
{
return
pattern
.
matcher
(
dependency
.
getTarget
().
getClassName
()).
matches
();
}
Pattern
pattern
;
}
/**
* This class accepts those dependencies whose class name is in a given
* package.
*/
static
class
TargetPackageFilter
implements
Filter
{
TargetPackageFilter
(
Set
<
String
>
packageNames
,
boolean
matchSubpackages
)
{
for
(
String
pn:
packageNames
)
{
if
(
pn
.
length
()
==
0
)
// implies null check as well
throw
new
IllegalArgumentException
();
}
this
.
packageNames
=
packageNames
;
this
.
matchSubpackages
=
matchSubpackages
;
}
public
boolean
accepts
(
Dependency
dependency
)
{
String
cn
=
dependency
.
getTarget
().
getClassName
();
int
lastSep
=
cn
.
lastIndexOf
(
"/"
);
String
pn
=
(
lastSep
==
-
1
?
""
:
cn
.
substring
(
0
,
lastSep
));
if
(
packageNames
.
contains
(
pn
))
return
true
;
if
(
matchSubpackages
)
{
for
(
String
n:
packageNames
)
{
if
(
pn
.
startsWith
(
n
+
"."
))
return
true
;
}
}
return
false
;
}
Set
<
String
>
packageNames
;
boolean
matchSubpackages
;
}
/**
* This class identifies class names directly or indirectly in the constant pool.
*/
static
class
ClassDependencyFinder
extends
BasicDependencyFinder
{
public
Iterable
<?
extends
Dependency
>
findDependencies
(
ClassFile
classfile
)
{
Visitor
v
=
new
Visitor
(
classfile
);
for
(
CPInfo
cpInfo:
classfile
.
constant_pool
.
entries
())
{
v
.
scan
(
cpInfo
);
}
return
v
.
deps
;
}
}
/**
* This class identifies class names in the signatures of classes, fields,
* and methods in a class.
*/
static
class
APIDependencyFinder
extends
BasicDependencyFinder
{
APIDependencyFinder
(
int
access
)
{
switch
(
access
)
{
case
AccessFlags
.
ACC_PUBLIC
:
case
AccessFlags
.
ACC_PROTECTED
:
case
AccessFlags
.
ACC_PRIVATE
:
case
0
:
showAccess
=
access
;
break
;
default
:
throw
new
IllegalArgumentException
(
"invalid access 0x"
+
Integer
.
toHexString
(
access
));
}
}
public
Iterable
<?
extends
Dependency
>
findDependencies
(
ClassFile
classfile
)
{
try
{
Visitor
v
=
new
Visitor
(
classfile
);
v
.
addClass
(
classfile
.
super_class
);
v
.
addClasses
(
classfile
.
interfaces
);
// inner classes?
for
(
Field
f
:
classfile
.
fields
)
{
if
(
checkAccess
(
f
.
access_flags
))
v
.
scan
(
f
.
descriptor
,
f
.
attributes
);
}
for
(
Method
m
:
classfile
.
methods
)
{
if
(
checkAccess
(
m
.
access_flags
))
{
v
.
scan
(
m
.
descriptor
,
m
.
attributes
);
Exceptions_attribute
e
=
(
Exceptions_attribute
)
m
.
attributes
.
get
(
Attribute
.
Exceptions
);
if
(
e
!=
null
)
v
.
addClasses
(
e
.
exception_index_table
);
}
}
return
v
.
deps
;
}
catch
(
ConstantPoolException
e
)
{
throw
new
ClassFileError
(
e
);
}
}
boolean
checkAccess
(
AccessFlags
flags
)
{
// code copied from javap.Options.checkAccess
boolean
isPublic
=
flags
.
is
(
AccessFlags
.
ACC_PUBLIC
);
boolean
isProtected
=
flags
.
is
(
AccessFlags
.
ACC_PROTECTED
);
boolean
isPrivate
=
flags
.
is
(
AccessFlags
.
ACC_PRIVATE
);
boolean
isPackage
=
!(
isPublic
||
isProtected
||
isPrivate
);
if
((
showAccess
==
AccessFlags
.
ACC_PUBLIC
)
&&
(
isProtected
||
isPrivate
||
isPackage
))
return
false
;
else
if
((
showAccess
==
AccessFlags
.
ACC_PROTECTED
)
&&
(
isPrivate
||
isPackage
))
return
false
;
else
if
((
showAccess
==
0
)
&&
(
isPrivate
))
return
false
;
else
return
true
;
}
private
int
showAccess
;
}
static
abstract
class
BasicDependencyFinder
implements
Finder
{
private
Map
<
String
,
Location
>
locations
=
new
HashMap
<
String
,
Location
>();
Location
getLocation
(
String
className
)
{
Location
l
=
locations
.
get
(
className
);
if
(
l
==
null
)
locations
.
put
(
className
,
l
=
new
SimpleLocation
(
className
));
return
l
;
}
class
Visitor
implements
ConstantPool
.
Visitor
<
Void
,
Void
>,
Type
.
Visitor
<
Void
,
Void
>
{
private
ConstantPool
constant_pool
;
private
Set
<
Dependency
>
deps
;
private
Location
origin
;
Visitor
(
ClassFile
classFile
)
{
try
{
constant_pool
=
classFile
.
constant_pool
;
origin
=
getLocation
(
classFile
.
getName
());
deps
=
new
HashSet
<
Dependency
>();
}
catch
(
ConstantPoolException
e
)
{
throw
new
ClassFileError
(
e
);
}
}
void
scan
(
Descriptor
d
,
Attributes
attrs
)
{
try
{
scan
(
new
Signature
(
d
.
index
).
getType
(
constant_pool
));
Signature_attribute
sa
=
(
Signature_attribute
)
attrs
.
get
(
Attribute
.
Signature
);
if
(
sa
!=
null
)
scan
(
new
Signature
(
sa
.
signature_index
).
getType
(
constant_pool
));
}
catch
(
ConstantPoolException
e
)
{
throw
new
ClassFileError
(
e
);
}
}
void
scan
(
CPInfo
cpInfo
)
{
cpInfo
.
accept
(
this
,
null
);
}
void
scan
(
Type
t
)
{
t
.
accept
(
this
,
null
);
}
void
addClass
(
int
index
)
throws
ConstantPoolException
{
if
(
index
!=
0
)
{
String
name
=
constant_pool
.
getClassInfo
(
index
).
getBaseName
();
if
(
name
!=
null
)
addDependency
(
name
);
}
}
void
addClasses
(
int
[]
indices
)
throws
ConstantPoolException
{
for
(
int
i:
indices
)
addClass
(
i
);
}
private
void
addDependency
(
String
name
)
{
deps
.
add
(
new
SimpleDependency
(
origin
,
getLocation
(
name
)));
}
// ConstantPool.Visitor methods
public
Void
visitClass
(
CONSTANT_Class_info
info
,
Void
p
)
{
try
{
if
(
info
.
getName
().
startsWith
(
"["
))
new
Signature
(
info
.
name_index
).
getType
(
constant_pool
).
accept
(
this
,
null
);
else
addDependency
(
info
.
getBaseName
());
return
null
;
}
catch
(
ConstantPoolException
e
)
{
throw
new
ClassFileError
(
e
);
}
}
public
Void
visitDouble
(
CONSTANT_Double_info
info
,
Void
p
)
{
return
null
;
}
public
Void
visitFieldref
(
CONSTANT_Fieldref_info
info
,
Void
p
)
{
return
visitRef
(
info
,
p
);
}
public
Void
visitFloat
(
CONSTANT_Float_info
info
,
Void
p
)
{
return
null
;
}
public
Void
visitInteger
(
CONSTANT_Integer_info
info
,
Void
p
)
{
return
null
;
}
public
Void
visitInterfaceMethodref
(
CONSTANT_InterfaceMethodref_info
info
,
Void
p
)
{
return
visitRef
(
info
,
p
);
}
public
Void
visitLong
(
CONSTANT_Long_info
info
,
Void
p
)
{
return
null
;
}
public
Void
visitNameAndType
(
CONSTANT_NameAndType_info
info
,
Void
p
)
{
try
{
new
Signature
(
info
.
type_index
).
getType
(
constant_pool
).
accept
(
this
,
null
);
return
null
;
}
catch
(
ConstantPoolException
e
)
{
throw
new
ClassFileError
(
e
);
}
}
public
Void
visitMethodref
(
CONSTANT_Methodref_info
info
,
Void
p
)
{
return
visitRef
(
info
,
p
);
}
public
Void
visitString
(
CONSTANT_String_info
info
,
Void
p
)
{
return
null
;
}
public
Void
visitUtf8
(
CONSTANT_Utf8_info
info
,
Void
p
)
{
return
null
;
}
private
Void
visitRef
(
CPRefInfo
info
,
Void
p
)
{
try
{
visitClass
(
info
.
getClassInfo
(),
p
);
return
null
;
}
catch
(
ConstantPoolException
e
)
{
throw
new
ClassFileError
(
e
);
}
}
// Type.Visitor methods
private
void
findDependencies
(
Type
t
)
{
if
(
t
!=
null
)
t
.
accept
(
this
,
null
);
}
private
void
findDependencies
(
List
<?
extends
Type
>
ts
)
{
if
(
ts
!=
null
)
{
for
(
Type
t:
ts
)
t
.
accept
(
this
,
null
);
}
}
public
Void
visitSimpleType
(
SimpleType
type
,
Void
p
)
{
return
null
;
}
public
Void
visitArrayType
(
ArrayType
type
,
Void
p
)
{
findDependencies
(
type
.
elemType
);
return
null
;
}
public
Void
visitMethodType
(
MethodType
type
,
Void
p
)
{
findDependencies
(
type
.
paramTypes
);
findDependencies
(
type
.
returnType
);
findDependencies
(
type
.
throwsTypes
);
return
null
;
}
public
Void
visitClassSigType
(
ClassSigType
type
,
Void
p
)
{
findDependencies
(
type
.
superclassType
);
findDependencies
(
type
.
superinterfaceTypes
);
return
null
;
}
public
Void
visitClassType
(
ClassType
type
,
Void
p
)
{
findDependencies
(
type
.
outerType
);
addDependency
(
type
.
name
);
findDependencies
(
type
.
typeArgs
);
return
null
;
}
public
Void
visitTypeParamType
(
TypeParamType
type
,
Void
p
)
{
findDependencies
(
type
.
classBound
);
findDependencies
(
type
.
interfaceBounds
);
return
null
;
}
public
Void
visitWildcardType
(
WildcardType
type
,
Void
p
)
{
findDependencies
(
type
.
boundType
);
return
null
;
}
}
}
}
src/share/classes/com/sun/tools/classfile/Dependency.java
0 → 100644
浏览文件 @
974e831f
/*
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
com.sun.tools.classfile
;
/**
* A directed relationship between two {@link Dependency.Location Location}s.
* Subtypes of {@code Dependency} may provide additional detail about the dependency.
*
* @see Dependency.Finder
* @see Dependency.Filter
* @see Dependencies
*/
public
interface
Dependency
{
/**
* A filter used to select dependencies of interest, and to discard others.
*/
public
interface
Filter
{
/**
* Return true if the dependency is of interest.
* @param dependency the dependency to be considered
* @return true if and only if the dependency is of interest.
*/
boolean
accepts
(
Dependency
dependency
);
}
/**
* An interface for finding the immediate dependencies of a given class file.
*/
public
interface
Finder
{
/**
* Find the immediate dependencies of a given class file.
* @param classfile the class file to be examined
* @return the set of dependencies located in the given class file.
*/
public
Iterable
<?
extends
Dependency
>
findDependencies
(
ClassFile
classfile
);
}
/**
* A location somewhere within a class. Subtypes of {@code Location}
* may be used to provide additional detail about the location.
*/
public
interface
Location
{
/**
* Get the name of the class containing the location.
* This name will be used to locate the class file for transitive
* dependency analysis.
* @return the name of the class containing the location.
*/
String
getClassName
();
}
/**
* Get the location that has the dependency.
* @return the location that has the dependency.
*/
Location
getOrigin
();
/**
* Get the location that is being depended upon.
* @return the location that is being depended upon.
*/
Location
getTarget
();
}
test/tools/javap/classfile/deps/GetDeps.java
0 → 100644
浏览文件 @
974e831f
/*
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import
java.io.*
;
import
java.util.*
;
import
java.util.regex.Pattern
;
import
javax.tools.*
;
import
com.sun.tools.classfile.*
;
import
com.sun.tools.classfile.Dependencies.*
;
import
com.sun.tools.classfile.Dependency.Location
;
import
com.sun.tools.javac.file.JavacFileManager
;
import
com.sun.tools.javac.util.Context
;
/**
* Demo utility for using the classfile dependency analysis API framework.
*
* Usage:
* getdeps [options] classes
* where options include:
* -classpath path where to find classes to analyze
* -p package-name restrict analysis to classes in this package
* (may be given multiple times)
* -r regex restrict analysis to packages matching pattern
* (-p and -r are exclusive)
* -rev invert the dependencies in the output
* -t transitive closure of dependencies
*/
public
class
GetDeps
{
public
static
void
main
(
String
...
args
)
throws
Exception
{
new
GetDeps
().
run
(
args
);
}
void
run
(
String
...
args
)
throws
IOException
,
ClassFileNotFoundException
{
PrintWriter
pw
=
new
PrintWriter
(
System
.
out
);
try
{
run
(
pw
,
args
);
}
finally
{
pw
.
flush
();
}
}
void
run
(
PrintWriter
out
,
String
...
args
)
throws
IOException
,
ClassFileNotFoundException
{
decodeArgs
(
args
);
final
StandardJavaFileManager
fm
=
new
JavacFileManager
(
new
Context
(),
false
,
null
);
if
(
classpath
!=
null
)
fm
.
setLocation
(
StandardLocation
.
CLASS_PATH
,
classpath
);
ClassFileReader
reader
=
new
ClassFileReader
(
fm
);
Dependencies
d
=
new
Dependencies
();
if
(
regex
!=
null
)
d
.
setFilter
(
Dependencies
.
getRegexFilter
(
Pattern
.
compile
(
regex
)));
if
(
packageNames
.
size
()
>
0
)
d
.
setFilter
(
Dependencies
.
getPackageFilter
(
packageNames
,
false
));
SortedRecorder
r
=
new
SortedRecorder
(
reverse
);
d
.
findAllDependencies
(
reader
,
rootClassNames
,
transitiveClosure
,
r
);
SortedMap
<
Location
,
SortedSet
<
Dependency
>>
deps
=
r
.
getMap
();
for
(
Map
.
Entry
<
Location
,
SortedSet
<
Dependency
>>
e:
deps
.
entrySet
())
{
out
.
println
(
e
.
getKey
());
for
(
Dependency
dep:
e
.
getValue
())
{
out
.
println
(
" "
+
dep
.
getTarget
());
}
}
}
void
decodeArgs
(
String
...
args
)
{
rootClassNames
=
new
TreeSet
<
String
>();
packageNames
=
new
TreeSet
<
String
>();
for
(
int
i
=
0
;
i
<
args
.
length
;
i
++)
{
String
arg
=
args
[
i
];
if
(
arg
.
equals
(
"-classpath"
)
&&
(
i
+
1
<
args
.
length
))
classpath
=
getPathFiles
(
args
[++
i
]);
else
if
(
arg
.
equals
(
"-p"
)
&&
(
i
+
1
<
args
.
length
))
packageNames
.
add
(
args
[++
i
]);
else
if
(
arg
.
equals
(
"-r"
)
&&
(
i
+
1
<
args
.
length
))
regex
=
args
[++
i
];
else
if
(
arg
.
equals
(
"-rev"
))
reverse
=
true
;
else
if
(
arg
.
equals
(
"-t"
))
transitiveClosure
=
true
;
else
if
(
arg
.
startsWith
(
"-"
))
throw
new
Error
(
arg
);
else
{
for
(
;
i
<
args
.
length
;
i
++)
rootClassNames
.
add
(
args
[
i
]);
}
}
}
List
<
File
>
getPathFiles
(
String
path
)
{
List
<
File
>
files
=
new
ArrayList
<
File
>();
for
(
String
p:
path
.
split
(
File
.
pathSeparator
))
{
if
(
p
.
length
()
>
0
)
files
.
add
(
new
File
(
p
));
}
return
files
;
}
boolean
transitiveClosure
;
List
<
File
>
classpath
;
Set
<
String
>
rootClassNames
;
Set
<
String
>
packageNames
;
String
regex
;
boolean
reverse
;
static
class
ClassFileReader
implements
Dependencies
.
ClassFileReader
{
private
JavaFileManager
fm
;
ClassFileReader
(
JavaFileManager
fm
)
{
this
.
fm
=
fm
;
}
@Override
public
ClassFile
getClassFile
(
String
className
)
throws
ClassFileNotFoundException
{
try
{
JavaFileObject
fo
=
fm
.
getJavaFileForInput
(
StandardLocation
.
CLASS_PATH
,
className
,
JavaFileObject
.
Kind
.
CLASS
);
if
(
fo
==
null
)
fo
=
fm
.
getJavaFileForInput
(
StandardLocation
.
PLATFORM_CLASS_PATH
,
className
,
JavaFileObject
.
Kind
.
CLASS
);
if
(
fo
==
null
)
throw
new
ClassFileNotFoundException
(
className
);
InputStream
in
=
fo
.
openInputStream
();
try
{
return
ClassFile
.
read
(
in
);
}
finally
{
in
.
close
();
}
}
catch
(
ConstantPoolException
e
)
{
throw
new
ClassFileNotFoundException
(
className
,
e
);
}
catch
(
IOException
e
)
{
throw
new
ClassFileNotFoundException
(
className
,
e
);
}
}
};
static
class
SortedRecorder
implements
Recorder
{
public
SortedRecorder
(
boolean
reverse
)
{
this
.
reverse
=
reverse
;
}
public
void
addDependency
(
Dependency
d
)
{
Location
o
=
(
reverse
?
d
.
getTarget
()
:
d
.
getOrigin
());
SortedSet
<
Dependency
>
odeps
=
map
.
get
(
o
);
if
(
odeps
==
null
)
{
Comparator
<
Dependency
>
c
=
(
reverse
?
originComparator
:
targetComparator
);
map
.
put
(
o
,
odeps
=
new
TreeSet
<
Dependency
>(
c
));
}
odeps
.
add
(
d
);
}
public
SortedMap
<
Location
,
SortedSet
<
Dependency
>>
getMap
()
{
return
map
;
}
private
Comparator
<
Dependency
>
originComparator
=
new
Comparator
<
Dependency
>()
{
public
int
compare
(
Dependency
o1
,
Dependency
o2
)
{
return
o1
.
getTarget
().
toString
().
compareTo
(
o2
.
getOrigin
().
toString
());
}
};
private
Comparator
<
Dependency
>
targetComparator
=
new
Comparator
<
Dependency
>()
{
public
int
compare
(
Dependency
o1
,
Dependency
o2
)
{
return
o1
.
getTarget
().
toString
().
compareTo
(
o2
.
getTarget
().
toString
());
}
};
private
Comparator
<
Location
>
locationComparator
=
new
Comparator
<
Location
>()
{
public
int
compare
(
Location
o1
,
Location
o2
)
{
return
o1
.
toString
().
compareTo
(
o2
.
toString
());
}
};
private
final
SortedMap
<
Location
,
SortedSet
<
Dependency
>>
map
=
new
TreeMap
<
Location
,
SortedSet
<
Dependency
>>(
locationComparator
);
boolean
reverse
;
}
}
test/tools/javap/classfile/deps/T6907575.java
0 → 100644
浏览文件 @
974e831f
/*
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6907575
* @build GetDeps p.C1
* @run main T6907575
*/
import
java.io.*
;
public
class
T6907575
{
public
static
void
main
(
String
...
args
)
throws
Exception
{
new
T6907575
().
run
();
}
void
run
()
throws
Exception
{
String
testSrc
=
System
.
getProperty
(
"test.src"
);
String
testClasses
=
System
.
getProperty
(
"test.classes"
);
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
);
GetDeps
gd
=
new
GetDeps
();
gd
.
run
(
pw
,
"-classpath"
,
testClasses
,
"-t"
,
"-p"
,
"p"
,
"p/C1"
);
pw
.
close
();
System
.
out
.
println
(
sw
);
String
ref
=
readFile
(
new
File
(
testSrc
,
"T6907575.out"
));
diff
(
sw
.
toString
().
replaceAll
(
"[\r\n]+"
,
"\n"
),
ref
);
}
void
diff
(
String
actual
,
String
ref
)
throws
Exception
{
System
.
out
.
println
(
"EXPECT:>>>"
+
ref
+
"<<<"
);
System
.
out
.
println
(
"ACTUAL:>>>"
+
actual
+
"<<<"
);
if
(!
actual
.
equals
(
ref
))
throw
new
Exception
(
"output not as expected"
);
}
String
readFile
(
File
f
)
throws
IOException
{
Reader
r
=
new
FileReader
(
f
);
char
[]
buf
=
new
char
[(
int
)
f
.
length
()];
int
offset
=
0
;
int
n
;
while
(
offset
<
buf
.
length
&&
(
n
=
r
.
read
(
buf
,
offset
,
buf
.
length
-
offset
))
!=
-
1
)
offset
+=
n
;
return
new
String
(
buf
,
0
,
offset
);
}
}
test/tools/javap/classfile/deps/T6907575.out
0 → 100644
浏览文件 @
974e831f
p/C1
java/lang/Object
p/C2
p/C2
java/lang/Object
p/C3
p/C3
java/lang/Object
test/tools/javap/classfile/deps/p/C1.java
0 → 100644
浏览文件 @
974e831f
/*
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
p
;
public
class
C1
{
C2
c2
;
}
class
C2
{
C3
c3
;
}
class
C3
{
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录