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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

计算结果:

temp var: 2987 milli seconds
instance var: 4039 milli seconds
static var: 3996 milli seconds
  • 1
  • 2
  • 3

这段代码中的每个方法都执行相同的循环,并反复相同的次数。唯一的不同是每个循环使一个不同类型的变量递增。方法 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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

计算结果:

temp var: 2973 milli seconds
instance var: 3074 milli seconds
static var: 3018 milli seconds
  • 1
  • 2
  • 3



我觉得还有个原因:

 jdk源码好多都是需要重新定义一个局部变量接受需要操作的数据的
这样可以保证原来的数据不被改变 ,这个是个人理解,如有不对请海量



转载来源 

https://blog.csdn.net/hl_java/article/details/79288909


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值