javac -parameters标志的缺点

时间:2017-05-19 10:20:05

标签: java-8 javac

我想尝试一些在运行时需要参数名称的框架功能,所以我需要使用-parameters编译我的应用程序,它会将参数名称存储在JVM字节代码中。

此参数用法存在除jar / war大小以外的哪些缺点?

2 个答案:

答案 0 :(得分:23)

在{8}中提供了对类文件格式的参数名称的添加,这是在Java 8中提供的。有一些关于为什么在OpenJDK电子邮件线程中包含参数名称是可选的讨论{ {3}}和JEP 118。简而言之,使参数名称可选的原因是关于类文件大小,兼容性表面和敏感信息暴露的担忧。

兼容性问题表面值得进一步讨论。上面链接的一个线程表示更改参数名称是二进制兼容的更改。这是事实,但仅限于JVM的二进制兼容性概念的严格背景下。也就是说,更改方法的参数名称永远不会改变JVM是否可以链接该方法。但该声明一般不具备兼容性。

历史上,参数名称被视为局部变量名称。 (毕竟,它们是本地的。)您可以随意更改它们,并且方法之外的任何内容都不会受到影响。但是,如果您启用对参数名称的反射访问,则突然您无法在不考虑程序的其他部分可能正在使用它的情况下更改名称。更糟糕的是,除非您对参数名称的所有使用都有严格的测试用例,或者您有一个非常好的静态分析器可以找到这些情况(我不知道其中一个),否则没有任何东西可以告诉您。

与使用Jackson(一个JSON处理库)的问题相关的注释,该问题具有将方法参数名称映射到JSON属性名称的功能。这可能非常方便,但这也意味着如果更改参数名称,JSON绑定可能会中断。更糟糕的是,如果程序基于Java方法参数名称生成JSON结构,则更改方法参数名称可能会静默更改数据格式或有线协议。显然,在这样的环境中,可靠地使用此功能意味着您必须进行非常好的测试,并在代码周围添加注释,指出哪些参数名称不能更改。

答案 1 :(得分:2)

唯一的事情是.class的大小会改变,因为字节码现在将包含更多信息:

public class DeleteMe3 {
    public static void main(String[] args) {
    }

    private static void go(String s) {
    }
}

例如,这将包含有关参数名称的信息,如:

private static void go(java.lang.String);
   descriptor: (Ljava/lang/String;)V
   flags: ACC_PRIVATE, ACC_STATIC
   Code:
     stack=0, locals=1, args_size=1
       0: return
     LineNumberTable:
       line 11: 0
   MethodParameters:
     Name                           Flags
     s

如果没有MethodParameters,这个-parameters就不会出现。

可能有一些框架对此不起作用。这是一个Spring Data JPA Issue。我知道这件事是因为我们前一段时间才打到它并不得不升级(我没有遇到任何其他人)。