Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_langtools
提交
356b38b3
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看板
提交
356b38b3
编写于
12月 29, 2012
作者:
J
jjg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8004727: Add compiler support for parameter reflection
Reviewed-by: jjg Contributed-by: eric.mccorkle@oracle.com
上级
ce95d32c
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
713 addition
and
18 deletion
+713
-18
src/share/classes/com/sun/tools/classfile/Attribute.java
src/share/classes/com/sun/tools/classfile/Attribute.java
+4
-1
src/share/classes/com/sun/tools/classfile/ClassWriter.java
src/share/classes/com/sun/tools/classfile/ClassWriter.java
+10
-1
src/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java
...s/com/sun/tools/classfile/MethodParameters_attribute.java
+87
-0
src/share/classes/com/sun/tools/javac/code/Symbol.java
src/share/classes/com/sun/tools/javac/code/Symbol.java
+2
-1
src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+48
-14
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+24
-0
src/share/classes/com/sun/tools/javac/main/Option.java
src/share/classes/com/sun/tools/javac/main/Option.java
+2
-0
src/share/classes/com/sun/tools/javac/resources/javac.properties
...re/classes/com/sun/tools/javac/resources/javac.properties
+2
-0
src/share/classes/com/sun/tools/javac/util/Names.java
src/share/classes/com/sun/tools/javac/util/Names.java
+2
-0
src/share/classes/com/sun/tools/javap/AttributeWriter.java
src/share/classes/com/sun/tools/javap/AttributeWriter.java
+24
-1
test/tools/javac/MethodParameters.java
test/tools/javac/MethodParameters.java
+343
-0
test/tools/javap/MethodParameters.java
test/tools/javap/MethodParameters.java
+165
-0
未找到文件。
src/share/classes/com/sun/tools/classfile/Attribute.java
浏览文件 @
356b38b3
/*
* Copyright (c) 2007, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 201
2
, 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
...
...
@@ -51,6 +51,7 @@ public abstract class Attribute {
public
static
final
String
LineNumberTable
=
"LineNumberTable"
;
public
static
final
String
LocalVariableTable
=
"LocalVariableTable"
;
public
static
final
String
LocalVariableTypeTable
=
"LocalVariableTypeTable"
;
public
static
final
String
MethodParameters
=
"MethodParameters"
;
public
static
final
String
RuntimeVisibleAnnotations
=
"RuntimeVisibleAnnotations"
;
public
static
final
String
RuntimeInvisibleAnnotations
=
"RuntimeInvisibleAnnotations"
;
public
static
final
String
RuntimeVisibleParameterAnnotations
=
"RuntimeVisibleParameterAnnotations"
;
...
...
@@ -113,6 +114,7 @@ public abstract class Attribute {
standardAttributes
.
put
(
LocalVariableTypeTable
,
LocalVariableTypeTable_attribute
.
class
);
if
(!
compat
)
{
// old javap does not recognize recent attributes
standardAttributes
.
put
(
MethodParameters
,
MethodParameters_attribute
.
class
);
standardAttributes
.
put
(
CompilationID
,
CompilationID_attribute
.
class
);
standardAttributes
.
put
(
RuntimeInvisibleAnnotations
,
RuntimeInvisibleAnnotations_attribute
.
class
);
standardAttributes
.
put
(
RuntimeInvisibleParameterAnnotations
,
RuntimeInvisibleParameterAnnotations_attribute
.
class
);
...
...
@@ -171,6 +173,7 @@ public abstract class Attribute {
R
visitLineNumberTable
(
LineNumberTable_attribute
attr
,
P
p
);
R
visitLocalVariableTable
(
LocalVariableTable_attribute
attr
,
P
p
);
R
visitLocalVariableTypeTable
(
LocalVariableTypeTable_attribute
attr
,
P
p
);
R
visitMethodParameters
(
MethodParameters_attribute
attr
,
P
p
);
R
visitRuntimeVisibleAnnotations
(
RuntimeVisibleAnnotations_attribute
attr
,
P
p
);
R
visitRuntimeInvisibleAnnotations
(
RuntimeInvisibleAnnotations_attribute
attr
,
P
p
);
R
visitRuntimeVisibleParameterAnnotations
(
RuntimeVisibleParameterAnnotations_attribute
attr
,
P
p
);
...
...
src/share/classes/com/sun/tools/classfile/ClassWriter.java
浏览文件 @
356b38b3
/*
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
2
, 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
...
...
@@ -479,6 +479,15 @@ public class ClassWriter {
out
.
writeShort
(
entry
.
index
);
}
public
Void
visitMethodParameters
(
MethodParameters_attribute
attr
,
ClassOutputStream
out
)
{
out
.
writeByte
(
attr
.
method_parameter_table
.
length
);
for
(
MethodParameters_attribute
.
Entry
e
:
attr
.
method_parameter_table
)
{
out
.
writeShort
(
e
.
name_index
);
out
.
writeInt
(
e
.
flags
);
}
return
null
;
}
public
Void
visitRuntimeVisibleAnnotations
(
RuntimeVisibleAnnotations_attribute
attr
,
ClassOutputStream
out
)
{
annotationWriter
.
write
(
attr
.
annotations
,
out
);
return
null
;
...
...
src/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java
0 → 100644
浏览文件 @
356b38b3
/*
* Copyright (c) 2012, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
com.sun.tools.classfile
;
import
java.io.IOException
;
/**
* See JVMS, section 4.8.13.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public
class
MethodParameters_attribute
extends
Attribute
{
public
final
int
method_parameter_table_length
;
public
final
Entry
[]
method_parameter_table
;
MethodParameters_attribute
(
ClassReader
cr
,
int
name_index
,
int
length
)
throws
IOException
{
super
(
name_index
,
length
);
method_parameter_table_length
=
cr
.
readUnsignedByte
();
method_parameter_table
=
new
Entry
[
method_parameter_table_length
];
for
(
int
i
=
0
;
i
<
method_parameter_table_length
;
i
++)
method_parameter_table
[
i
]
=
new
Entry
(
cr
);
}
public
MethodParameters_attribute
(
ConstantPool
constant_pool
,
Entry
[]
method_parameter_table
)
throws
ConstantPoolException
{
this
(
constant_pool
.
getUTF8Index
(
Attribute
.
MethodParameters
),
method_parameter_table
);
}
public
MethodParameters_attribute
(
int
name_index
,
Entry
[]
method_parameter_table
)
{
super
(
name_index
,
1
+
method_parameter_table
.
length
*
Entry
.
length
());
this
.
method_parameter_table_length
=
method_parameter_table
.
length
;
this
.
method_parameter_table
=
method_parameter_table
;
}
public
<
R
,
D
>
R
accept
(
Visitor
<
R
,
D
>
visitor
,
D
data
)
{
return
visitor
.
visitMethodParameters
(
this
,
data
);
}
public
static
class
Entry
{
Entry
(
ClassReader
cr
)
throws
IOException
{
name_index
=
cr
.
readUnsignedShort
();
flags
=
cr
.
readInt
();
}
public
static
int
length
()
{
return
6
;
}
public
final
int
name_index
;
public
final
int
flags
;
}
}
src/share/classes/com/sun/tools/javac/code/Symbol.java
浏览文件 @
356b38b3
...
...
@@ -1283,8 +1283,9 @@ public abstract class Symbol implements Element {
List
<
Name
>
paramNames
=
savedParameterNames
;
savedParameterNames
=
null
;
// discard the provided names if the list of names is the wrong size.
if
(
paramNames
==
null
||
paramNames
.
size
()
!=
type
.
getParameterTypes
().
size
())
if
(
paramNames
==
null
||
paramNames
.
size
()
!=
type
.
getParameterTypes
().
size
())
{
paramNames
=
List
.
nil
();
}
ListBuffer
<
VarSymbol
>
buf
=
new
ListBuffer
<
VarSymbol
>();
List
<
Name
>
remaining
=
paramNames
;
// assert: remaining and paramNames are both empty or both
...
...
src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
浏览文件 @
356b38b3
...
...
@@ -217,6 +217,13 @@ public class ClassReader implements Completer {
*/
boolean
haveParameterNameIndices
;
/** Set this to false every time we start reading a method
* and are saving parameter names. Set it to true when we see
* MethodParameters, if it's set when we see a LocalVariableTable,
* then we ignore the parameter names from the LVT.
*/
boolean
sawMethodParameters
;
/**
* The set of attribute names for which warnings have been generated for the current class
*/
...
...
@@ -984,7 +991,7 @@ public class ClassReader implements Completer {
new
AttributeReader
(
names
.
LocalVariableTable
,
V45_3
,
CLASS_OR_MEMBER_ATTRIBUTE
)
{
protected
void
read
(
Symbol
sym
,
int
attrLen
)
{
int
newbp
=
bp
+
attrLen
;
if
(
saveParameterNames
)
{
if
(
saveParameterNames
&&
!
sawMethodParameters
)
{
// Pick up parameter names from the variable table.
// Parameter names are not explicitly identified as such,
// but all parameter name entries in the LocalVariableTable
...
...
@@ -1017,6 +1024,25 @@ public class ClassReader implements Completer {
}
},
new
AttributeReader
(
names
.
MethodParameters
,
V52
,
MEMBER_ATTRIBUTE
)
{
protected
void
read
(
Symbol
sym
,
int
attrlen
)
{
int
newbp
=
bp
+
attrlen
;
if
(
saveParameterNames
)
{
sawMethodParameters
=
true
;
int
numEntries
=
nextByte
();
parameterNameIndices
=
new
int
[
numEntries
];
haveParameterNameIndices
=
true
;
for
(
int
i
=
0
;
i
<
numEntries
;
i
++)
{
int
nameIndex
=
nextChar
();
int
flags
=
nextInt
();
parameterNameIndices
[
i
]
=
nameIndex
;
}
}
bp
=
newbp
;
}
},
new
AttributeReader
(
names
.
SourceFile
,
V45_3
,
CLASS_ATTRIBUTE
)
{
protected
void
read
(
Symbol
sym
,
int
attrLen
)
{
ClassSymbol
c
=
(
ClassSymbol
)
sym
;
...
...
@@ -1826,6 +1852,7 @@ public class ClassReader implements Completer {
}
else
Arrays
.
fill
(
parameterNameIndices
,
0
);
haveParameterNameIndices
=
false
;
sawMethodParameters
=
false
;
}
/**
...
...
@@ -1845,12 +1872,16 @@ public class ClassReader implements Completer {
// if no names were found in the class file, there's nothing more to do
if
(!
haveParameterNameIndices
)
return
;
int
firstParam
=
((
sym
.
flags
()
&
STATIC
)
==
0
)
?
1
:
0
;
// the code in readMethod may have skipped the first parameter when
// setting up the MethodType. If so, we make a corresponding allowance
// here for the position of the first parameter. Note that this
// assumes the skipped parameter has a width of 1 -- i.e. it is not
// If we get parameter names from MethodParameters, then we
// don't need to skip.
int
firstParam
=
0
;
if
(!
sawMethodParameters
)
{
firstParam
=
((
sym
.
flags
()
&
STATIC
)
==
0
)
?
1
:
0
;
// the code in readMethod may have skipped the first
// parameter when setting up the MethodType. If so, we
// make a corresponding allowance here for the position of
// the first parameter. Note that this assumes the
// skipped parameter has a width of 1 -- i.e. it is not
// a double width type (long or double.)
if
(
sym
.
name
==
names
.
init
&&
currentOwner
.
hasOuterInstance
())
{
// Sometimes anonymous classes don't have an outer
...
...
@@ -1861,17 +1892,20 @@ public class ClassReader implements Completer {
}
if
(
sym
.
type
!=
jvmType
)
{
// reading the method attributes has caused the symbol's type to
// be changed. (i.e. the Signature attribute.) This may happen if
// there are hidden (synthetic) parameters in the descriptor, but
// not in the Signature. The position of these hidden parameters
// is unspecified; for now, assume they are at the beginning, and
// so skip over them. The primary case for this is two hidden
// parameters passed into Enum constructors.
// reading the method attributes has caused the
// symbol's type to be changed. (i.e. the Signature
// attribute.) This may happen if there are hidden
// (synthetic) parameters in the descriptor, but not
// in the Signature. The position of these hidden
// parameters is unspecified; for now, assume they are
// at the beginning, and so skip over them. The
// primary case for this is two hidden parameters
// passed into Enum constructors.
int
skip
=
Code
.
width
(
jvmType
.
getParameterTypes
())
-
Code
.
width
(
sym
.
type
.
getParameterTypes
());
firstParam
+=
skip
;
}
}
List
<
Name
>
paramNames
=
List
.
nil
();
int
index
=
firstParam
;
for
(
Type
t:
sym
.
type
.
getParameterTypes
())
{
...
...
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
浏览文件 @
356b38b3
...
...
@@ -725,6 +725,28 @@ public class ClassWriter extends ClassFile {
return
acount
;
}
/**
* Write method parameter names attribute.
*/
int
writeMethodParametersAttr
(
MethodSymbol
m
)
{
if
(
m
.
params
!=
null
&&
0
!=
m
.
params
.
length
())
{
int
attrIndex
=
writeAttr
(
names
.
MethodParameters
);
databuf
.
appendByte
(
m
.
params
.
length
());
for
(
VarSymbol
s
:
m
.
params
)
{
// TODO: expand to cover synthesized, once we figure out
// how to represent that.
final
int
flags
=
(
int
)
s
.
flags
()
&
(
FINAL
|
SYNTHETIC
);
// output parameter info
databuf
.
appendChar
(
pool
.
put
(
s
.
name
));
databuf
.
appendInt
(
flags
);
}
endAttr
(
attrIndex
);
return
1
;
}
else
return
0
;
}
/** Write method parameter annotations;
* return number of attributes written.
*/
...
...
@@ -1034,6 +1056,8 @@ public class ClassWriter extends ClassFile {
endAttr
(
alenIdx
);
acount
++;
}
if
(
options
.
isSet
(
PARAMETERS
))
acount
+=
writeMethodParametersAttr
(
m
);
acount
+=
writeMemberAttrs
(
m
);
acount
+=
writeParameterAttrs
(
m
);
endAttrs
(
acountIdx
,
acount
);
...
...
src/share/classes/com/sun/tools/javac/main/Option.java
浏览文件 @
356b38b3
...
...
@@ -176,6 +176,8 @@ public enum Option {
PROCESSORPATH
(
"-processorpath"
,
"opt.arg.path"
,
"opt.processorpath"
,
STANDARD
,
FILEMANAGER
),
PARAMETERS
(
"-parameters"
,
"opt.parameters"
,
STANDARD
,
BASIC
),
D
(
"-d"
,
"opt.arg.directory"
,
"opt.d"
,
STANDARD
,
FILEMANAGER
),
S
(
"-s"
,
"opt.arg.directory"
,
"opt.sourceDest"
,
STANDARD
,
FILEMANAGER
),
...
...
src/share/classes/com/sun/tools/javac/resources/javac.properties
浏览文件 @
356b38b3
...
...
@@ -55,6 +55,8 @@ javac.opt.processorpath=\
Specify where to find annotation processors
javac.opt.processor
=
\
Names of the annotation processors to run; bypasses default discovery process
javac.opt.parameters
=
\
Generate metadata for reflection on method parameters
javac.opt.proc.none.only
=
\
Control whether annotation processing and/or compilation is done.
javac.opt.d
=
\
...
...
src/share/classes/com/sun/tools/javac/util/Names.java
浏览文件 @
356b38b3
...
...
@@ -132,6 +132,7 @@ public class Names {
public
final
Name
LineNumberTable
;
public
final
Name
LocalVariableTable
;
public
final
Name
LocalVariableTypeTable
;
public
final
Name
MethodParameters
;
public
final
Name
RuntimeInvisibleAnnotations
;
public
final
Name
RuntimeInvisibleParameterAnnotations
;
public
final
Name
RuntimeInvisibleTypeAnnotations
;
...
...
@@ -265,6 +266,7 @@ public class Names {
LineNumberTable
=
fromString
(
"LineNumberTable"
);
LocalVariableTable
=
fromString
(
"LocalVariableTable"
);
LocalVariableTypeTable
=
fromString
(
"LocalVariableTypeTable"
);
MethodParameters
=
fromString
(
"MethodParameters"
);
RuntimeInvisibleAnnotations
=
fromString
(
"RuntimeInvisibleAnnotations"
);
RuntimeInvisibleParameterAnnotations
=
fromString
(
"RuntimeInvisibleParameterAnnotations"
);
RuntimeInvisibleTypeAnnotations
=
fromString
(
"RuntimeInvisibleTypeAnnotations"
);
...
...
src/share/classes/com/sun/tools/javap/AttributeWriter.java
浏览文件 @
356b38b3
/*
* Copyright (c) 2007, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 201
2
, 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
...
...
@@ -46,6 +46,7 @@ import com.sun.tools.classfile.InnerClasses_attribute;
import
com.sun.tools.classfile.LineNumberTable_attribute
;
import
com.sun.tools.classfile.LocalVariableTable_attribute
;
import
com.sun.tools.classfile.LocalVariableTypeTable_attribute
;
import
com.sun.tools.classfile.MethodParameters_attribute
;
import
com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute
;
import
com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute
;
import
com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute
;
...
...
@@ -386,6 +387,28 @@ public class AttributeWriter extends BasicWriter
return
null
;
}
private
static
final
String
format
=
"%-31s%s"
;
public
Void
visitMethodParameters
(
MethodParameters_attribute
attr
,
Void
ignore
)
{
final
String
header
=
String
.
format
(
format
,
"Name"
,
"Flags"
);
println
(
"MethodParameters:"
);
indent
(+
1
);
println
(
header
);
for
(
MethodParameters_attribute
.
Entry
entry
:
attr
.
method_parameter_table
)
{
String
flagstr
=
(
0
!=
(
entry
.
flags
&
ACC_FINAL
)
?
" final"
:
""
)
+
(
0
!=
(
entry
.
flags
&
ACC_SYNTHETIC
)
?
" synthetic"
:
""
);
println
(
String
.
format
(
format
,
constantWriter
.
stringValue
(
entry
.
name_index
),
flagstr
));
}
indent
(-
1
);
return
null
;
}
public
Void
visitRuntimeVisibleAnnotations
(
RuntimeVisibleAnnotations_attribute
attr
,
Void
ignore
)
{
println
(
"RuntimeVisibleAnnotations:"
);
indent
(+
1
);
...
...
test/tools/javac/MethodParameters.java
0 → 100644
浏览文件 @
356b38b3
/*
* Copyright (c) 2012, 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
* @summary javac should generate method parameters correctly.
*/
// key: opt.arg.parameters
import
com.sun.tools.classfile.*
;
import
com.sun.tools.javac.file.JavacFileManager
;
import
com.sun.tools.javac.main.Main
;
import
com.sun.tools.javac.util.Context
;
import
com.sun.tools.javac.util.Name
;
import
com.sun.tools.javac.util.Names
;
import
java.io.*
;
import
javax.lang.model.element.*
;
import
java.util.*
;
public
class
MethodParameters
{
static
final
String
Foo_name
=
"Foo"
;
static
final
String
Foo_contents
=
"public class Foo {\n"
+
" Foo() {}\n"
+
" void foo0() {}\n"
+
" void foo2(int j, int k) {}\n"
+
"}"
;
static
final
String
Bar_name
=
"Bar"
;
static
final
String
Bar_contents
=
"public class Bar {\n"
+
" Bar(int i) {}"
+
" Foo foo() { return new Foo(); }\n"
+
"}"
;
static
final
String
Baz_name
=
"Baz"
;
static
final
String
Baz_contents
=
"public class Baz {\n"
+
" int baz;"
+
" Baz(int i) {}"
+
"}"
;
static
final
String
Qux_name
=
"Qux"
;
static
final
String
Qux_contents
=
"public class Qux extends Baz {\n"
+
" Qux(int i) { super(i); }"
+
"}"
;
static
final
File
classesdir
=
new
File
(
"methodparameters"
);
public
static
void
main
(
String
...
args
)
throws
Exception
{
new
MethodParameters
().
run
();
}
void
run
()
throws
Exception
{
classesdir
.
mkdir
();
final
File
Foo_java
=
writeFile
(
classesdir
,
Foo_name
+
".java"
,
Foo_contents
);
final
File
Bar_java
=
writeFile
(
classesdir
,
Bar_name
+
".java"
,
Bar_contents
);
final
File
Baz_java
=
writeFile
(
classesdir
,
Baz_name
+
".java"
,
Baz_contents
);
System
.
err
.
println
(
"Test compile with -parameter"
);
compile
(
"-parameters"
,
"-d"
,
classesdir
.
getPath
(),
Foo_java
.
getPath
());
// First test: make sure javac doesn't choke to death on
// MethodParameter attributes
System
.
err
.
println
(
"Test compile with classfile containing MethodParameter attributes"
);
compile
(
"-parameters"
,
"-d"
,
classesdir
.
getPath
(),
"-cp"
,
classesdir
.
getPath
(),
Bar_java
.
getPath
());
System
.
err
.
println
(
"Examine class foo"
);
checkFoo
();
checkBar
();
System
.
err
.
println
(
"Test debug information conflict"
);
compile
(
"-g"
,
"-parameters"
,
"-d"
,
classesdir
.
getPath
(),
"-cp"
,
classesdir
.
getPath
(),
Baz_java
.
getPath
());
System
.
err
.
println
(
"Introducing debug information conflict"
);
Baz_java
.
delete
();
modifyBaz
(
false
);
System
.
err
.
println
(
"Checking language model"
);
inspectBaz
();
System
.
err
.
println
(
"Permuting attributes"
);
modifyBaz
(
true
);
System
.
err
.
println
(
"Checking language model"
);
inspectBaz
();
if
(
0
!=
errors
)
throw
new
Exception
(
"MethodParameters test failed with "
+
errors
+
" errors"
);
}
void
inspectBaz
()
throws
Exception
{
final
File
Qux_java
=
writeFile
(
classesdir
,
Qux_name
+
".java"
,
Qux_contents
);
final
String
[]
args
=
{
"-XDsave-parameter-names"
,
"-d"
,
classesdir
.
getPath
(),
"-cp"
,
classesdir
.
getPath
(),
Qux_java
.
getPath
()
};
final
StringWriter
sw
=
new
StringWriter
();
final
PrintWriter
pw
=
new
PrintWriter
(
sw
);
// We need to be able to crack open javac and look at its data
// structures. We'll rig up a compiler instance, but keep its
// Context, thus allowing us to get at the ClassReader.
Context
context
=
new
Context
();
Main
comp
=
new
Main
(
"javac"
,
pw
);
JavacFileManager
.
preRegister
(
context
);
// Compile Qux, which uses Baz.
comp
.
compile
(
args
,
context
);
pw
.
close
();
final
String
out
=
sw
.
toString
();
if
(
out
.
length
()
>
0
)
System
.
err
.
println
(
out
);
// Now get the class reader, construct a name for Baz, and load it.
com
.
sun
.
tools
.
javac
.
jvm
.
ClassReader
cr
=
com
.
sun
.
tools
.
javac
.
jvm
.
ClassReader
.
instance
(
context
);
Name
name
=
Names
.
instance
(
context
).
fromString
(
Baz_name
);
// Now walk down the language model and check the name of the
// parameter.
final
Element
baz
=
cr
.
loadClass
(
name
);
for
(
Element
e
:
baz
.
getEnclosedElements
())
{
if
(
e
instanceof
ExecutableElement
)
{
final
ExecutableElement
ee
=
(
ExecutableElement
)
e
;
final
List
<?
extends
VariableElement
>
params
=
ee
.
getParameters
();
if
(
1
!=
params
.
size
())
throw
new
Exception
(
"Classfile Baz badly formed: wrong number of methods"
);
final
VariableElement
param
=
params
.
get
(
0
);
if
(!
param
.
getSimpleName
().
contentEquals
(
"baz"
))
{
errors
++;
System
.
err
.
println
(
"javac did not correctly resolve the metadata conflict, parameter's name reads as "
+
param
.
getSimpleName
());
}
else
System
.
err
.
println
(
"javac did correctly resolve the metadata conflict"
);
}
}
}
void
modifyBaz
(
boolean
flip
)
throws
Exception
{
final
File
Baz_class
=
new
File
(
classesdir
,
Baz_name
+
".class"
);
final
ClassFile
baz
=
ClassFile
.
read
(
Baz_class
);
final
int
ind
=
baz
.
constant_pool
.
getUTF8Index
(
"baz"
);
MethodParameters_attribute
mpattr
=
null
;
int
mpind
=
0
;
Code_attribute
cattr
=
null
;
int
cind
=
0
;
// Find the indexes of the MethodParameters and the Code attributes
if
(
baz
.
methods
.
length
!=
1
)
throw
new
Exception
(
"Classfile Baz badly formed: wrong number of methods"
);
if
(!
baz
.
methods
[
0
].
getName
(
baz
.
constant_pool
).
equals
(
"<init>"
))
throw
new
Exception
(
"Classfile Baz badly formed: method has name "
+
baz
.
methods
[
0
].
getName
(
baz
.
constant_pool
));
for
(
int
i
=
0
;
i
<
baz
.
methods
[
0
].
attributes
.
attrs
.
length
;
i
++)
{
if
(
baz
.
methods
[
0
].
attributes
.
attrs
[
i
]
instanceof
MethodParameters_attribute
)
{
mpattr
=
(
MethodParameters_attribute
)
baz
.
methods
[
0
].
attributes
.
attrs
[
i
];
mpind
=
i
;
}
else
if
(
baz
.
methods
[
0
].
attributes
.
attrs
[
i
]
instanceof
Code_attribute
)
{
cattr
=
(
Code_attribute
)
baz
.
methods
[
0
].
attributes
.
attrs
[
i
];
cind
=
i
;
}
}
if
(
null
==
mpattr
)
throw
new
Exception
(
"Classfile Baz badly formed: no method parameters info"
);
if
(
null
==
cattr
)
throw
new
Exception
(
"Classfile Baz badly formed: no local variable table"
);
int
flags
=
mpattr
.
method_parameter_table
[
0
].
flags
;
// Alter the MethodParameters attribute, changing the name of
// the parameter from i to baz. This requires Black Magic...
//
// The (well-designed) classfile library (correctly) does not
// allow us to mess around with the attribute data structures,
// or arbitrarily generate new ones.
//
// Instead, we install a new subclass of Attribute that
// hijacks the Visitor pattern and outputs the sequence of
// bytes that we want. This only works in this particular
// instance, because we know we'll only every see one kind of
// visitor.
//
// If anyone ever changes the makeup of the Baz class, or
// tries to install some kind of visitor that gets run prior
// to serialization, this will break.
baz
.
methods
[
0
].
attributes
.
attrs
[
mpind
]
=
new
Attribute
(
mpattr
.
attribute_name_index
,
mpattr
.
attribute_length
)
{
public
<
R
,
D
>
R
accept
(
Visitor
<
R
,
D
>
visitor
,
D
data
)
{
if
(
data
instanceof
ByteArrayOutputStream
)
{
ByteArrayOutputStream
out
=
(
ByteArrayOutputStream
)
data
;
out
.
write
(
1
);
out
.
write
((
ind
>>
8
)
&
0xff
);
out
.
write
(
ind
&
0xff
);
out
.
write
((
flags
>>
24
)
&
0xff
);
out
.
write
((
flags
>>
16
)
&
0xff
);
out
.
write
((
flags
>>
8
)
&
0xff
);
out
.
write
(
flags
&
0xff
);
}
else
throw
new
RuntimeException
(
"Output stream is of type "
+
data
.
getClass
()
+
", which is not handled by this test. Update the test and it should work."
);
return
null
;
}
};
// Flip the code and method attributes. This is for checking
// that order doesn't matter.
if
(
flip
)
{
baz
.
methods
[
0
].
attributes
.
attrs
[
mpind
]
=
cattr
;
baz
.
methods
[
0
].
attributes
.
attrs
[
cind
]
=
mpattr
;
}
new
ClassWriter
().
write
(
baz
,
Baz_class
);
}
// Run a bunch of structural tests on foo to make sure it looks right.
void
checkFoo
()
throws
Exception
{
final
File
Foo_class
=
new
File
(
classesdir
,
Foo_name
+
".class"
);
final
ClassFile
foo
=
ClassFile
.
read
(
Foo_class
);
for
(
int
i
=
0
;
i
<
foo
.
methods
.
length
;
i
++)
{
System
.
err
.
println
(
"Examine method Foo."
+
foo
.
methods
[
i
].
getName
(
foo
.
constant_pool
));
if
(
foo
.
methods
[
i
].
getName
(
foo
.
constant_pool
).
equals
(
"foo2"
))
{
for
(
int
j
=
0
;
j
<
foo
.
methods
[
i
].
attributes
.
attrs
.
length
;
j
++)
if
(
foo
.
methods
[
i
].
attributes
.
attrs
[
j
]
instanceof
MethodParameters_attribute
)
{
MethodParameters_attribute
mp
=
(
MethodParameters_attribute
)
foo
.
methods
[
i
].
attributes
.
attrs
[
j
];
System
.
err
.
println
(
"Foo.foo2 should have 2 parameters: j and k"
);
if
(
2
!=
mp
.
method_parameter_table_length
)
error
(
"expected 2 method parameter entries in foo2, got "
+
mp
.
method_parameter_table_length
);
else
if
(!
foo
.
constant_pool
.
getUTF8Value
(
mp
.
method_parameter_table
[
0
].
name_index
).
equals
(
"j"
))
error
(
"expected first parameter to foo2 to be \"j\", got \""
+
foo
.
constant_pool
.
getUTF8Value
(
mp
.
method_parameter_table
[
0
].
name_index
)
+
"\" instead"
);
else
if
(!
foo
.
constant_pool
.
getUTF8Value
(
mp
.
method_parameter_table
[
1
].
name_index
).
equals
(
"k"
))
error
(
"expected first parameter to foo2 to be \"k\", got \""
+
foo
.
constant_pool
.
getUTF8Value
(
mp
.
method_parameter_table
[
1
].
name_index
)
+
"\" instead"
);
}
}
else
if
(
foo
.
methods
[
i
].
getName
(
foo
.
constant_pool
).
equals
(
"<init>"
))
{
for
(
int
j
=
0
;
j
<
foo
.
methods
[
i
].
attributes
.
attrs
.
length
;
j
++)
{
if
(
foo
.
methods
[
i
].
attributes
.
attrs
[
j
]
instanceof
MethodParameters_attribute
)
error
(
"Zero-argument constructor shouldn't have MethodParameters"
);
}
}
else
if
(
foo
.
methods
[
i
].
getName
(
foo
.
constant_pool
).
equals
(
"foo0"
))
{
for
(
int
j
=
0
;
j
<
foo
.
methods
[
i
].
attributes
.
attrs
.
length
;
j
++)
if
(
foo
.
methods
[
i
].
attributes
.
attrs
[
j
]
instanceof
MethodParameters_attribute
)
error
(
"Zero-argument method shouldn't have MethodParameters"
);
}
else
error
(
"Unknown method "
+
foo
.
methods
[
i
].
getName
(
foo
.
constant_pool
)
+
" showed up in class Foo"
);
}
}
// Run a bunch of structural tests on Bar to make sure it looks right.
void
checkBar
()
throws
Exception
{
final
File
Bar_class
=
new
File
(
classesdir
,
Bar_name
+
".class"
);
final
ClassFile
bar
=
ClassFile
.
read
(
Bar_class
);
for
(
int
i
=
0
;
i
<
bar
.
methods
.
length
;
i
++)
{
System
.
err
.
println
(
"Examine method Bar."
+
bar
.
methods
[
i
].
getName
(
bar
.
constant_pool
));
if
(
bar
.
methods
[
i
].
getName
(
bar
.
constant_pool
).
equals
(
"<init>"
))
{
for
(
int
j
=
0
;
j
<
bar
.
methods
[
i
].
attributes
.
attrs
.
length
;
j
++)
if
(
bar
.
methods
[
i
].
attributes
.
attrs
[
j
]
instanceof
MethodParameters_attribute
)
{
MethodParameters_attribute
mp
=
(
MethodParameters_attribute
)
bar
.
methods
[
i
].
attributes
.
attrs
[
j
];
System
.
err
.
println
(
"Bar constructor should have 1 parameter: i"
);
if
(
1
!=
mp
.
method_parameter_table_length
)
error
(
"expected 1 method parameter entries in constructor, got "
+
mp
.
method_parameter_table_length
);
else
if
(!
bar
.
constant_pool
.
getUTF8Value
(
mp
.
method_parameter_table
[
0
].
name_index
).
equals
(
"i"
))
error
(
"expected first parameter to foo2 to be \"i\", got \""
+
bar
.
constant_pool
.
getUTF8Value
(
mp
.
method_parameter_table
[
0
].
name_index
)
+
"\" instead"
);
}
}
else
if
(
bar
.
methods
[
i
].
getName
(
bar
.
constant_pool
).
equals
(
"foo"
))
{
for
(
int
j
=
0
;
j
<
bar
.
methods
[
i
].
attributes
.
attrs
.
length
;
j
++)
{
if
(
bar
.
methods
[
i
].
attributes
.
attrs
[
j
]
instanceof
MethodParameters_attribute
)
error
(
"Zero-argument constructor shouldn't have MethodParameters"
);
}
}
}
}
String
compile
(
String
...
args
)
throws
Exception
{
System
.
err
.
println
(
"compile: "
+
Arrays
.
asList
(
args
));
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
);
int
rc
=
com
.
sun
.
tools
.
javac
.
Main
.
compile
(
args
,
pw
);
pw
.
close
();
String
out
=
sw
.
toString
();
if
(
out
.
length
()
>
0
)
System
.
err
.
println
(
out
);
if
(
rc
!=
0
)
error
(
"compilation failed, rc="
+
rc
);
return
out
;
}
File
writeFile
(
File
dir
,
String
path
,
String
body
)
throws
IOException
{
File
f
=
new
File
(
dir
,
path
);
f
.
getParentFile
().
mkdirs
();
FileWriter
out
=
new
FileWriter
(
f
);
out
.
write
(
body
);
out
.
close
();
return
f
;
}
void
error
(
String
msg
)
{
System
.
err
.
println
(
"Error: "
+
msg
);
errors
++;
}
int
errors
;
}
test/tools/javap/MethodParameters.java
0 → 100644
浏览文件 @
356b38b3
/*
* Copyright (c) 2010, 2012, 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
* @summary javac should generate method parameters correctly.
*/
import
java.io.*
;
import
java.util.*
;
public
class
MethodParameters
{
static
final
String
Foo_name
=
"Foo"
;
static
final
String
Foo_contents
=
(
"public class Foo {\n"
+
" Foo() {}\n"
+
" Foo(int i) {}\n"
+
" void foo0() {}\n"
+
" void foo2(int j, int k) {}\n"
+
"}"
).
replaceAll
(
" +"
,
" "
);
static
final
String
Init0_expected
=
(
" Foo();\n"
+
" flags: \n"
+
" Code:\n"
+
" stack=1, locals=1, args_size=1\n"
+
" 0: aload_0 \n"
+
" 1: invokespecial #1 // Method java/lang/Object.\"<init>\":()V\n"
+
" 4: return \n"
+
" LineNumberTable:\n"
+
" line 2: 0"
).
replaceAll
(
" +"
,
" "
);
static
final
String
Init1_expected
=
(
" Foo(int);\n"
+
" flags: \n"
+
" Code:\n"
+
" stack=1, locals=2, args_size=2\n"
+
" 0: aload_0 \n"
+
" 1: invokespecial #1 // Method java/lang/Object.\"<init>\":()V\n"
+
" 4: return \n"
+
" LineNumberTable:\n"
+
" line 3: 0\n"
+
" MethodParameters:\n"
+
" Name Flags\n"
+
" i"
).
replaceAll
(
" +"
,
" "
);
static
final
String
foo0_expected
=
(
" void foo0();\n"
+
" flags: \n"
+
" Code:\n"
+
" stack=0, locals=1, args_size=1\n"
+
" 0: return \n"
+
" LineNumberTable:\n"
+
" line 4: 0"
).
replaceAll
(
" +"
,
" "
);
static
final
String
foo2_expected
=
(
" void foo2(int, int);\n"
+
" flags: \n"
+
" Code:\n"
+
" stack=0, locals=3, args_size=3\n"
+
" 0: return \n"
+
" LineNumberTable:\n"
+
" line 5: 0\n"
+
" MethodParameters:\n"
+
" Name Flags\n"
+
" j \n"
+
" k"
).
replaceAll
(
" +"
,
" "
);
static
final
File
classesdir
=
new
File
(
"methodparameters"
);
static
final
String
separator
=
System
.
getProperty
(
"line.separator"
);
public
static
void
main
(
String
...
args
)
throws
Exception
{
new
MethodParameters
().
run
();
}
void
run
()
throws
Exception
{
classesdir
.
mkdir
();
final
File
Foo_java
=
writeFile
(
classesdir
,
Foo_name
+
".java"
,
Foo_contents
);
compile
(
"-parameters"
,
"-d"
,
classesdir
.
getPath
(),
Foo_java
.
getPath
());
System
.
out
.
println
(
"Run javap"
);
String
output
=
javap
(
"-c"
,
"-verbose"
,
"-classpath"
,
classesdir
.
getPath
(),
Foo_name
);
String
normalized
=
output
.
replaceAll
(
separator
,
"\n"
).
replaceAll
(
" +"
,
" "
);
if
(!
normalized
.
contains
(
Init0_expected
))
error
(
"Bad output for zero-parameter constructor. Expected\n"
+
Init0_expected
+
"\n"
+
"but got\n"
+
normalized
);
if
(!
normalized
.
contains
(
Init1_expected
))
error
(
"Bad output for one-parameter constructor. Expected\n"
+
Init1_expected
+
"\n"
+
"but got\n"
+
normalized
);
if
(!
normalized
.
contains
(
foo0_expected
))
error
(
"Bad output for zero-parameter method. Expected\n"
+
foo0_expected
+
"\n"
+
"but got\n"
+
normalized
);
if
(!
normalized
.
contains
(
foo2_expected
))
error
(
"Bad output for two-parameter method Expected\n"
+
foo2_expected
+
"\n"
+
"but got\n"
+
normalized
);
if
(
0
!=
errors
)
throw
new
Exception
(
"MethodParameters test failed with "
+
errors
+
" errors"
);
}
String
javap
(
String
...
args
)
{
StringWriter
sw
=
new
StringWriter
();
PrintWriter
out
=
new
PrintWriter
(
sw
);
//sun.tools.javap.Main.entry(args);
int
rc
=
com
.
sun
.
tools
.
javap
.
Main
.
run
(
args
,
out
);
if
(
rc
!=
0
)
throw
new
Error
(
"javap failed. rc="
+
rc
);
out
.
close
();
System
.
out
.
println
(
sw
);
return
sw
.
toString
();
}
String
compile
(
String
...
args
)
throws
Exception
{
System
.
err
.
println
(
"compile: "
+
Arrays
.
asList
(
args
));
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
);
int
rc
=
com
.
sun
.
tools
.
javac
.
Main
.
compile
(
args
,
pw
);
pw
.
close
();
String
out
=
sw
.
toString
();
if
(
out
.
length
()
>
0
)
System
.
err
.
println
(
out
);
if
(
rc
!=
0
)
error
(
"compilation failed, rc="
+
rc
);
return
out
;
}
File
writeFile
(
File
dir
,
String
path
,
String
body
)
throws
IOException
{
File
f
=
new
File
(
dir
,
path
);
f
.
getParentFile
().
mkdirs
();
FileWriter
out
=
new
FileWriter
(
f
);
out
.
write
(
body
);
out
.
close
();
return
f
;
}
void
error
(
String
msg
)
{
System
.
err
.
println
(
"Error: "
+
msg
);
errors
++;
}
int
errors
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录