Java 枚举和其他类文件 [英] Java enum and additional class files

查看:16
本文介绍了Java 枚举和其他类文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到 enums 在编译后引入了许多额外的类文件 (Class$1),使总大小膨胀.它似乎附加到每个甚至使用枚举的类中,而且这些经常是重复的.

I've noticed enums introduce many additional class files (Class$1) after compilation bloating the total size. It seems to be attached to every class that even uses an enum, and these are often duplicated.

为什么会发生这种情况,有没有办法在不删除枚举的情况下防止这种情况发生.

Why does this occur and is there a way to prevent this without removing the enum.

(问题的原因是空间对我来说非常宝贵)

(Reason for question is space is at a premium for me)

编辑

在进一步调查此问题时,Sun 的Javac 1.6 会在您每次在 Enum 上使用开关时创建一个额外的合成类.它使用某种 SwitchMap.这个站点有更多信息,这里告诉你如何分析Javac正在做什么.

On investigating the issue further, Sun's Javac 1.6 creates an additional synthetic class each time you use a switch on an Enum. It uses some kind of SwitchMap. This site has some more information, and here tells you how to analyse what Javac is doing.

每次在枚举上使用开关时,额外的物理文件似乎都需要付出高昂的代价!

An additional physical file seems a high price to pay each time you use a switch on an enum!

有趣的是,Eclipe 的编译器不会生成这些附加文件.我想知道是否唯一的解决方案是切换编译器?

Interestingly, Eclipe's compiler does not produce these additional files. I wonder if the only solution is to switch compilers?

推荐答案

我只是被这种行为所困扰,在谷歌搜索时出现了这个问题.我想我会分享一些我发现的额外信息.

I was just bit by this behavior and this question showed up when Googling. I thought I'd share the little bit of extra information I found out.

每次在枚举上使用开关时,javac 1.5 和 1.6 都会创建一个额外的合成类.该类包含一个所谓的切换映射",它将枚举索引映射到切换表跳转编号.重要的是,合成类是为发生切换的类创建的,不是枚举类.

javac 1.5 and 1.6 create an additional synthetic class each time you use a switch on an enum. The class contains a so-called "switch map" which maps enum indices to switch table jump numbers. Importantly, the synthetic class is created for the class in which the switch occurs, not the enum class.

以下是生成内容的示例:

Here's an example of what gets generated:

public enum EnumClass { VALUE1, VALUE2, VALUE3 }

EnumUser.java

public class EnumUser {
    public String getName(EnumClass value) {
        switch (value) {
            case VALUE1: return "value 1";
            // No VALUE2 case.
            case VALUE3: return "value 3";
            default:     return "other";
        }
    }
}

合成 EnumUser$1.class

class EnumUser$1 {
    static final int[] $SwitchMap$EnumClass = new int[EnumClass.values().length];

    static {
        $SwitchMap$EnumClass[EnumClass.VALUE1.ordinal()] = 1;
        $SwitchMap$EnumClass[EnumClass.VALUE3.ordinal()] = 2;
    };
}

此开关映射然后用于为 lookupswitchtableswitch JVM 指令生成索引.它将每个枚举值转换为从 1 到 [开关案例数] 的相应索引.

This switch map is then used to generate an index for a lookupswitch or tableswitch JVM instruction. It converts each enum value into a corresponding index from 1 to [number of switch cases].

public java.lang.String getName(EnumClass);
  Code:
   0:   getstatic       #2; //Field EnumUser$1.$SwitchMap$EnumClass:[I
   3:   aload_1
   4:   invokevirtual   #3; //Method EnumClass.ordinal:()I
   7:   iaload
   8:   lookupswitch{ //2
                1: 36;
                2: 39;
                default: 42 }
   36:  ldc     #4; //String value 1
   38:  areturn
   39:  ldc     #5; //String value 3
   41:  areturn
   42:  ldc     #6; //String other
   44:  areturn

tableswitch 用于三个或更多开关情况,因为与 lookupswitch 的线性搜索相比,它执行更有效的恒定时间查找.从技术上讲,当 javac 使用 lookupswitch 时,它可以使用合成开关映射省略整个业务.

tableswitch is used if there are three or more switch cases as it performs a more efficient constant-time lookup vs. lookupswitch's linear search. Technically speaking javac could omit this whole business with the synthetic switch map when it uses lookupswitch.

推测:我手头没有 Eclipse 的编译器来测试,但我想它不会打扰合成类,只需使用 lookupswitch.或者,它可能需要比原始提问者在升级"到 tableswitch 之前测试的更多 switch 案例.

Speculation: I don't have Eclipse's compiler on hand to test with but I imagine that it doesn't bother with a synthetic class and simply uses lookupswitch. Or perhaps it requires more switch cases than the original asker tested with before it "ugprades" to tableswitch.

这篇关于Java 枚举和其他类文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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