【问题标题】:Can a JIT take a benefit from Generics?JIT 可以从泛型中受益吗?
【发布时间】:2011-10-14 02:03:07
【问题描述】:

众所周知,泛型类型在编译过程中无法生存。它们被类强制转换所取代。

但是,类型信息存在于类文件中,可以使用反射查看:

public class Demo
{
    private List<String> list;

    public Demo() throws SecurityException, NoSuchFieldException
    {
        System.out.println(((Class<?>)((ParameterizedType) getClass().getDeclaredField("list").getGenericType()).getActualTypeArguments()[0]).getName());
    }

    public static void main(String[] args) throws SecurityException, NoSuchFieldException
    {
        new Demo();
    }
}

执行时,将打印java.lang.String

JIT 能否将其用于某种优化?还是从 JIT 的角度来看这些信息是无用的?

【问题讨论】:

    标签: java optimization jit


    【解决方案1】:

    可以,但据我所知没有。为了解决这个问题,Scala 最近增加了对通用代码的编译时type specialization 的支持,该通用代码生成该类的专用版本 - 没有任何强制转换 - 并将它们透明地放置到代码库的其余部分,以便代码仍然按预期工作.在这些情况下,编译后的 Scala 代码实际上可能比 Java 快得多,因为带有泛型的 Java 将始终使用强制类型转换。

    【讨论】:

    • 但这对内存使用有负面影响,因为代码比较多,不是吗?
    • 是的,这是一个权衡。不过,内存并不是当今最稀缺的资源。
    • @yankee 当然,但是 C++ 模板确实一直存在这个问题,到目前为止它对他们来说效果很好。虽然这也与一些巧妙的优化有关(即组合产生相同机器代码的方法),但我怀疑 Java 编译器会这样做(这是一个不平凡的问题,javac 非常简单)
    • @Voo javac 可能很简单,但这只是因为繁重的工作是由 JIT 和运行时完成的。他们都进行了大量的优化和反优化以产生最佳的实际运行机器代码,javac 生成的字节码只是中介。
    • @Esko 是的,JIT 完成了繁重的工作,但在某个时间点,我认为在运行时折叠方法会非常复杂(或至少相当昂贵)。而 javac 的目标是成为一个简单的编译器——我们所说的这种优化会违背这个原则。事实上,afaik 是 Hotspot 的来源,在这方面没有做任何事情(可能是因为 scala 对他们来说并不那么重要)
    【解决方案2】:

    JVM 不可能避免强制转换对象,因为底层集合可能没有字符串。例如如果使用擦除将整数添加到列表中。

    我想不出潜在的优化,而且 JIT 没有做很多潜在的优化。 ;)

    【讨论】:

      猜你喜欢
      • 2021-05-28
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 1970-01-01
      • 2012-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多