受jvm / jvm-options影响的代码示例

时间:2015-02-17 18:10:30

标签: java jvm

我正在寻找代码示例,结果取决于以下内容:

  • Java版本
  • VM
  • Java选项/ JVM选项

示例将是以下代码:

Integer foo = 400;
Integer bar = 400;
System.out.println(foo == bar)

查看该代码,很多人会猜测,这是错误的,但它取决于IntegerCache.high的值,可以使用-Djava.lang.Integer.IntegerCache.high = 1000更改

我想,有很多例子可以改变内存限制的行为,但是有更多意想不到的例子吗?

1 个答案:

答案 0 :(得分:3)

Java版本影响力:

1)看看这样的读者:

public class Reader {
   private final String input;
   private int currentPosition;
   private Pattern numberPattern = Pattern.compile(...);

   public String readNextInt() {
       return numberPattern.matcher(input.substring(currentPosition)).group();
   }
}

在早于7的Java版本中,此代码可以正常工作,因为String.substring()只共享其内部缓冲区并存储两个指向缓冲区开始/结束的指针。但是在Java 7中,这种行为发生了变化,现在每个substring()调用都会创建一个带有自己缓冲区的新String对象,这会大大影响这段代码的性能,尤其是在字符串较大的情况下。

2)当Java 1.2发布时,所有中间浮点运算仅表示为单精度或双精度,这会导致多个舍入错误。 1.2 JVM之后可以将中间结果表示为80位扩展双精度,从而大大提高了精度。因此,您可以在不同的处理器和不同版本的Java上观察不同的浮点结果。

为了向后兼容或不同架构之间的兼容性,有strictfp修饰符。

3)在Java 8中,所有与反射相关的代码都经过了高度优化,因此切换到更新版本将显着提高任何与反射相关的代码的性能。看看一些基准here

4)Java 5和JSR-133。 JSR-133是一种全新的记忆模型,没有以前的缺陷。最终和易变的字段语义被改变了。此外,Java中并发编程的许多方面也都有所改变,因此您可以预期Java 5之前和之后的多线程程序的行为完全不同。您可以阅读有关JSR-133 here的更多信息。

5)在Java 7中更改了Mergesort实现。它可能导致旧代码抛出IllegalArgumentException。阅读更多here

6)每个新的java版本都会引入一些性能改进或错误修复,所以通常你会看到一些小的改进(甚至没有,例如在Java 8中大量增强的转义分析以避免在堆上分配lambda),但是很少见案例slowdowns也是可能的。

<强> VM: 除了热点之外,我对VM不太了解,但你可以期待一些JIT的改进/减速,不同的内存消耗和GC停顿(比如Azul Zulu的无间隙c4收集器和高内存要求)甚至是静态提前时间编译,就像在Excelsior JET中一样。但通常您在JVM实现之间切换时确切知道自己在做什么。

Java选项/ JVM选项:

1)偏向锁定。像-XX:+ UseBiasedLocking和-XX:BiasedLockingStartupDelay = n这样的标志可以根据您的并发配置文件改变应用程序的性能,因此使用这些标志可以增强和损害您的应用程序。例如。当你试图撤销偏置锁时,Azul Zulu的工程师只是因为不可避免的STW而给出了偏向锁定(是的,锁定撤销足够只停止两个线程,但是设计中只有热点的全局STW)。

2)XX:+ AlwaysPreTouch标志在JVM启动时触摸并清零所有内存页面,以避免在运行时受到惩罚并阻止linux窃取您的页面。

4)-XX:+ BindGCTaskThreadsT​​oCPU现在没有在JDK8中实现,但可能会在以后影响你的gc性能:)

5)-XX:+ UseNUMA可以提高您在NUMA架构上的性能,JVM将尝试为NUMA节点分区堆。 This article表示&#34;使用NUMA感知分配器可以将性能提高约40%&#34;。

6)-XX:+ UseCondCardMark可以帮助您进行高度并发的应用程序,以防止您不期望的错误共享。在java中,在512字节区域(&#34; cards&#34;)上分隔堆,并且程序中的每次写入都会导致对相应卡的易失性写入(外部对象的地址移位9)。因此,平均64张卡共享相同的L1缓存行。这意味着在一个32kByte(= 512 * 64)区域内的对象内写入会导致写入同一缓存行,这会降低应用程序性能。 -XX:+ UseCondCardMark用if (card[address >> 9] == 0) card[address >> 9] = 1替换那些写入卡表的写入,这可以减少每个竞争的32kB区域中从几百到一个的易失写入量。

7)有许多标志会影响GC的性能,但我确定你可以自己挖掘所有相关信息,因为在这里编写gc调优的所有建议都没有意义。