在编译的java类中保存参数/参数名称 [英] Preserving parameter/argument names in compiled java classes

查看:1582
本文介绍了在编译的java类中保存参数/参数名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public class MyClass 
{
void myMethod(String name,String options,String query,String comment)
{
...
}
}

并将其编译为类文件,似乎参数名称丢失。也就是说,当一些其他Java代码引用 MyClass 并且想要调用或覆盖 myMethod 时,我的IDE(目前为Eclipse)似乎从类文件中获取此方法签名:

  void myMethod(String arg0,String arg1,String arg2,String arg3 ); 

我知道Eclipse(也可能是其他的IDE)也允许我提供一个链接到源或可以利用这一点,javadoc (正如Bishiboosh指出的) MyClass 。但是,如果有一些方法可以告诉 javac 将名称包含在类文件中,那么我很好奇,因此该类的用户即使看到参数名称只有类文件。



课程解决方案



当我使用 java -g:vars ,参数的名称包含在类文件中。 -g:vars 似乎等同于Eclipse - >项目属性 - > Java编译器 - >将变量属性添加到生成的类文件。



这个解决方案是由几位作者提出的,但是尼克的答案终于让我相信。



在我的机器,Eclipse有时使用这个信息,有时它没有,这可能是我的错误或Eclipse中的错误,但不是类文件或编译的问题。无论如何,现在我知道这些信息绝对存在。



但是没有解决方案接口



(种)罚款,它不适用于接口。对于我来说,逻辑原因似乎是,-g:vars只提供局部变量的名称,这是javac的文档所说的。在一个方法的主体中,它的参数与局部变量非常相似,因此它们被-g:vars覆盖。界面方法没有实体,所以他们不能有局部变量。



我的初始问题只是要求上课,因为我不知道可能有任何差异。



类文件格式



根据 gid 指出,类文件格式不支持参数名称的存储。我在类文件规范中找到了部分描述一个数据struture,它应该是方法的参数名称,但是这在编译接口时绝对不会使用。



编译一个类时,我不能告诉是否使用了所提到的数据结构,或者如果Eclipse从方法体内的参数的使用推断参数名称。一个专家可以澄清这一点,但这并不是我想的。

解决方案

要保留类文件中的名称以进行调试,请尝试项目属性,Java编译器,然后将变量属性添加到生成的类文件(请参阅​​ Eclipse帮助)。



编译以下源:

  public class StackOverflowTest {
public void test(String foo,String bar){
// blah

}

反编译为:

  //从StackOverflowTest.java(版本1.5:49.0,超级位)编译
public class StackOverflowTest {

//方法描述符# 6()V
// Stack:1,Localals:1
public StackOverflowTest();
0 aload_0 [this]
1 invokespecial java.lang.Object()[8]
4 return
行号:
[pc:0,行:1 ]
本地变量表:
[pc:0,pc:5] local:this index:0 type:StackOverflowTest

//方法描述符#15(Ljava / lang / String; Ljava / lang / String;)V
// Stack:0,Locals:3
public void test(java.lang.String foo,java.lang.String bar);
0返回
行号:
[pc:0,行:4]
本地变量表:
[pc:0,pc:1] local:this索引:0类型:StackOverflowTest
[pc:0,pc:1] local:foo index:1 type:java.lang.String
[pc:0,pc:1] local:bar index: 2类型:java.lang.String
}

参见名称保留在类文件



我会建议你研究你的源代码是如何编译的,哪个版本是为其编译的。



编辑:



啊,我看到接口不同 - 他们似乎没有这个信息可用于调试器,我猜是有道理的。我不认为会有这样的一个方法,如果您只是想在编辑源代码时看到参数名称,那么您需要以Nagrom_17建议(附加源)进行javadoc路由。


When I compile something like this:

public class MyClass
{
    void myMethod(String name, String options, String query, String comment)
    {
        ...
    }
}

and compile this to a class file, it seems that argument names are lost. That is, when some other Java code references MyClass and wants to call or overwrite myMethod, my IDE (currently Eclipse) seems to get this method signature from the class-file:

void myMethod(String arg0, String arg1, String arg2, String arg3);

I know that Eclipse (and possibly other IDEs too) allows me to provide a link to the source or the javadoc (as Bishiboosh pointed out) of MyClass and can take advantage of this. But I'm curious if there is some way to tell javac to include the names into the class-file, so that users of that class can see the argument names even if they only have the class file.

Solution for classes

When I compile a class with java -g:vars, the names of parameters are included in the class file. -g:vars seems to be equivalent to Eclipse -> project properties -> Java compiler -> Add variable attributes to generated class files.

This solution was suggested by several authors, but the answer from Nick finally made me believe.

On my machine, Eclipse sometimes used this info, sometimes it didn't, which was probably my fault or a bug in Eclipse, but not a problem with the class files or the compile. Anyway, now I know that the information is definitely present.

But no solution for interfaces

While this works (kind of) fine for classes, it's not working for interfaces.

For me, the logical reason seems to be, that -g:vars only provides the names of local variables, which is what the documentation for javac also states. In the body of a method, it's parameters are very similar to local variables, thus they are covered by -g:vars. interface methods don't have bodies, so they can't have local varibles.

My initial question only asked for classes, because I was not aware that there might be any difference.

Class file format

As gid pointed out, the class file format does not support storrage of parameter names. I found a section in the class file spec that descibes a data struture which should holf the parameter names of methods, but this is definitely not used when compiling interfaces.

When compiling a class, I can't tell if the mentioned data structure is used, or if Eclipse infers the parameter names from the usage of parameters inside the method body. An expert could clarify this, but it's not that relevant I think.

解决方案

To preserve names in the class file for debugging purposes try project properties, Java compiler, then "Add variable attributes to generated class files" (See Eclipse Help).

Compiling the following source:

public class StackOverflowTest {
    public void test(String foo, String bar) {
        // blah
    }
}

Is decompiled into:

// Compiled from StackOverflowTest.java (version 1.5 : 49.0, super bit)
public class StackOverflowTest {

    // Method descriptor #6 ()V
    // Stack: 1, Locals: 1
    public StackOverflowTest();
        0  aload_0 [this]
        1  invokespecial java.lang.Object() [8]
        4  return
        Line numbers:
            [pc: 0, line: 1]
        Local variable table:
            [pc: 0, pc: 5] local: this index: 0 type: StackOverflowTest

    // Method descriptor #15 (Ljava/lang/String;Ljava/lang/String;)V
    // Stack: 0, Locals: 3
    public void test(java.lang.String foo, java.lang.String bar);
        0  return
        Line numbers:
            [pc: 0, line: 4]
        Local variable table:
            [pc: 0, pc: 1] local: this index: 0 type: StackOverflowTest
            [pc: 0, pc: 1] local: foo index: 1 type: java.lang.String
            [pc: 0, pc: 1] local: bar index: 2 type: java.lang.String
}

See the parameter names are preserved in the class files.

I would suggest you look into how your source is being compiled, which version it is compiled for etc.

EDIT:

Ah, I see this is different for interfaces - they don't seem to have this information available for the debugger which I guess makes sense. I don't think there'll be a way round this, if you just want to see the parameter names when you're editing source you'll need to go the javadoc route as Nagrom_17 suggests (attach the source).

这篇关于在编译的java类中保存参数/参数名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆