JDK源码中为什么在方法中创建一个临时变量替代成员变量、类变量

JDK源码中为什么在方法中创建一个临时变量替代成员变量、类变量 又名 临时变量提高Java代码性能

一个Java类中可以存在多种形式的变量,可以是最一般的成员变量;或静态变量;或临时变量。那么这三种变量的存取效率如何?

1、实战出真知

package com.subject.variable;

/**
 * 使用临时变量提高Java代码性能 (转)
 */
public class VariableDemo {

    private long instVar;// 成员变量
    private static long staticVar; // 静态变量

    // 存取类方法中的临时变量
    void tempAccess(long val) {
        int j = 0;// 临时变量
        long startTime = System.currentTimeMillis();
        for (long i = 0; i < val; i++) {
            j += 1;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("temp var: " + (endTime - startTime) + " milli seconds");
    }

    // 存取类的成员变量
    void instanceAccess(long val) {
        long startTime = System.currentTimeMillis();
        for (long i = 0; i < val; i++) {
            instVar += 1;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("instance var: " + (endTime - startTime) + " milli seconds");
    }

    // 存取类的 static 变量
    void staticAccess(long val) {
        long startTime = System.currentTimeMillis();
        for (long i = 0; i < val; i++) {
            staticVar += 1;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("static var: " + (endTime - startTime) + " milli seconds");
    }

    public static void main(String[] args) {
        VariableDemo test = new VariableDemo();
        long count=10*1000*1000*1000L;
        test.tempAccess(count);
        test.instanceAccess(count);
        test.staticAccess(count);
    }
}

计算结果:

temp var: 2987 milli seconds
instance var: 4039 milli seconds
static var: 3996 milli seconds

这段代码中的每个方法都执行相同的循环,并反复相同的次数。唯一的不同是每个循环使一个不同类型的变量递增。方法 tempAccess 使一个局部堆栈变量递增,instanceAccess 使类的一个成员实例变量递增,而 staticAccess 使类的一个 static 变量递增。
从结果中可以发现,instanceAccess 和 staticAccess 的执行时间基本相同。但是,tempAccess 要快两到三倍。

2、JVM存取变量机制
存取堆栈变量如此快是因为JVM 存取堆栈变量比它存取 成员变量 或 静态变量执行的操作少。
JVM 是一种基于堆栈的虚拟机,因此优化了对堆栈数据的存取和处理。所有局部变量都存储在一个局部变量表中,在 Java 操作数堆栈中进行处理,并可被高效地存取。
存取 成员变量 和 静态变量 成本更高,因为 JVM 必须使用代价更高的操作码,并从常数存储池中存取它们。(常数存储池保存一个类型所使用的所有类型、字段和方法的符号引用。)通常,在第一次从常数存储池中访问 static 变量或实例变量以后,JVM 将动态更改字节码以使用效率更高的操作码。尽管有这种优化,堆栈变量的存取仍然更快。

3、那么如何优化代码
考虑到这些事实,就可以重新构建前面的代码,以便通过存取堆栈变量而不是实例变量或 static 变量使操作更高效。

package com.subject.variable;

/**
 * 使用临时变量提高Java代码性能 (转)
 */
public class VariableDemo2 {

    private long instVar;// 成员变量
    private static long staticVar; // 静态变量

    // 存取类方法中的临时变量
    void tempAccess(long val) {
        int j = 0;// 临时变量
        long startTime = System.currentTimeMillis();
        for (long i = 0; i < val; i++) {
            j += 1;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("temp var: " + (endTime - startTime) + " milli seconds");
    }

    // 存取类的成员变量
    void instanceAccess(long val) {
        long startTime = System.currentTimeMillis();
        long tmp=instVar;
        for (long i = 0; i < val; i++) {
            tmp += 1;
        }
        instVar=tmp;
        long endTime = System.currentTimeMillis();
        System.out.println("instance var: " + (endTime - startTime) + " milli seconds");
    }

    // 存取类的 static 变量
    void staticAccess(long val) {
        long startTime = System.currentTimeMillis();
        long tmp=staticVar;
        for (long i = 0; i < val; i++) {
            tmp += 1;
        }
        staticVar=tmp;
        long endTime = System.currentTimeMillis();
        System.out.println("static var: " + (endTime - startTime) + " milli seconds");
    }

    public static void main(String[] args) {
        VariableDemo2 test = new VariableDemo2();
        long count=10*1000*1000*1000L;
        test.tempAccess(count);
        test.instanceAccess(count);
        test.staticAccess(count);
    }
}

计算结果:

temp var: 2973 milli seconds
instance var: 3074 milli seconds
static var: 3018 milli seconds

转载来源
http://blog.csdn.net/yejin191258966/article/details/40195933
原文样式已经凌乱了,特重新进行了整理,并统一了术语,比如实例变量/成员变量,静态变量/static变量

猜你喜欢

转载自blog.csdn.net/hl_java/article/details/79288909