- 浏览: 277725 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
sjx19871109:
有一个疑问,博主在做循环的时候,for(int i=0;i&l ...
ArrayList:用add代替remove -
剑锋凛冽:
不错,看了很有帮助。但有个概念不是很清楚,锁投票是什么?
java中的lock和synchronized -
星期扒的幻想:
学习了,了解了
Solr增删改查 -
programming:
很蛋痛的webx 工程与jarsource编码不一直,相关 ...
Webx3 -
xjt927:
...
Solr增删改查
如果你频繁存取变量,就需要考虑从何处存取这些变量。变量是 static 变量,还是局部变量,或是类的实例变量?变量的存储位置对存取他的代码的性能有明显的影响?例如,请考虑下面这段代码:
class stackvars
{
private int instvar;
private static int staticvar;
//存取局部变量
void stackaccess(int val)
{
int j=0;
for (int i=0; i<val; i++)
j += 1;
}
//存取类的实例变量
void instanceaccess(int val)
{
for (int i=0; i<val; i++)
instvar += 1;
}
//存取类的 static 变量
void staticaccess(int val)
{
for (int i=0; i<val; i++)
staticvar += 1;
}
}
这段代码中的每个方法都执行相同的循环,并反复相同的次数。唯一的不同是每个循环使一个不同类型的变量递增。方法 stackaccess 使一个局部堆栈变量递增,instanceaccess 使类的一个实例变量递增,而 staticaccess 使类的一个 static 变量递增。
instanceaccess 和 staticaccess 的执行时间基本相同。不过,stackaccess 要快两到三倍。存取堆栈变量如此快是因为,jvm 存取堆栈变量比他存取 static 变量或类的实例变量执行的操作少。请看一下为这三个方法生成的字节码:
method void stackaccess(int)
0 iconst_0 //将 0 压入堆栈。
1 istore_2 //弹出 0 并将他存储在局部分变量表中索引为 2 的位置 (j)。
2 iconst_0 //压入 0。
3 istore_3 //弹出 0 并将他存储在局部变量表中索引为 3 的位置 (i)。
4 goto 13 //跳至位置 13。
7 iinc 2 1 //将存储在索引 2 处的 j 加 1。
10 iinc 3 1 //将存储在索引 3 处的 i 加 1。
13 iload_3 //压入索引 3 处的值 (i)。
14 iload_1 //压入索引 1 处的值 (val)。
15 if_icmplt 7 //弹出 i 和 val。如果 i 小于 val,则跳至位置 7。
18 return //返回调用方法。
method void instanceaccess(int)
0 iconst_0 //将 0 压入堆栈。
1 istore_2 //弹出 0 并将他存储在局部变量表中索引为 2 的位置 (i)。
2 goto 18 //跳至位置 18。
5 aload_0 //压入索引 0 (this)。
6 dup //复制堆栈顶的值并将他压入。
7 getfield #19 <field int instvar>
//弹出 this 对象引用并压入 instvar 的值。
10 iconst_1 //压入 1。
11 iadd //弹出栈顶的两个值,并压入他们的和。
12 putfield #19 <field int instvar>
//弹出栈顶的两个值并将和存储在 instvar 中。
15 iinc 2 1 //将存储在索引 2 处的 i 加 1。
18 iload_2 //压入索引 2 处的值 (i)。
19 iload_1 //压入索引 1 处的值 (val)。
20 if_icmplt 5 //弹出 i 和 val。如果 i 小于 val,则跳至位置 5。
23 return //返回调用方法。
method void staticaccess(int)
0 iconst_0 //将 0 压入堆栈。
1 istore_2 //弹出 0 并将他存储在局部变量表中索引为 2 的位置 (i)。
2 goto 16 //跳至位置 16。
5 getstatic #25 <field int staticvar>
//将常数存储池中 staticvar 的值压入堆栈。
8 iconst_1 //压入 1。
9 iadd //弹出栈顶的两个值,并压入他们的和。
10 putstatic #25 <field int staticvar>
//弹出和的值并将他存储在 staticvar 中。
13 iinc 2 1 //将存储在索引 2 处的 i 加 1。
16 iload_2 //压入索引 2 处的值 (i)。
17 iload_1 //压入索引 1 处的值 (val)。
18 if_icmplt 5 //弹出 i 和 val。如果 i 小于 val,则跳至位置 5。
21 return //返回调用方法。
查看字节码揭示了堆栈变量效率更高的原因。jvm 是一种基于堆栈的虚拟机,因此优化了对堆栈数据的存取和处理。所有局部变量都存储在一个局部变量表中,在 java 操作数堆栈中进行处理,并可被高效地存取。存取 static 变量和实例变量成本更高,因为 jvm 必须使用代价更高的操作码,并从常数存储池中存取他们。(常数存储池保存一个类型所使用的所有类型、字段和方法的符号引用。)
通常,在第一次从常数存储池中访问 static 变量或实例变量以后,jvm 将动态更改字节码以使用效率更高的操作码。尽管有这种优化,堆栈变量的存取仍然更快。
考虑到这些事实,就能重新构建前面的代码,以便通过存取堆栈变量而不是实例变量或 static 变量使操作更高效。请考虑修改后的代码:
class stackvars
{
//和前面相同...
void instanceaccess(int val)
{
int j = instvar;
for (int i=0; i<val; i++)
j += 1;
instvar = j;
}
void staticaccess(int val)
{
int j = staticvar;
for (int i=0; i<val; i++)
j += 1;
staticvar = j;
}
}
方法 instanceaccess 和 staticaccess 被修改为将他们的实例变量或 static 变量复制到局部堆栈变量中。当变量的处理完成以后,其值又被复制回实例变量或 static 变量中。这种简单的更改明显提高了 instanceaccess 和 staticaccess 的性能。这三个方法的执行时间目前基本相同,instanceaccess 和 staticaccess 的执行速度只比 stackaccess 的执行速度慢大约 4%。
这并不表示你应该避免使用 static 变量或实例变量。你应该使用对你的设计有意义的存储机制。例如,如果你在一个循环中存取 static 变量或实例变量,则你能临时将他们存储在一个局部堆栈变量中,这样就能明显地提高代码的性能。这将提供最高效的字节码指令序列供 jvm 执行。
发表评论
-
多线程 Future 异常处理
2017-03-14 19:15 1285http://www.blogjava.net/xylz/ar ... -
问题排查记录-linux
2016-08-05 12:02 808### 以下所有命令都要先sudo su admin ... -
打完整含依赖包的jar包
2015-04-10 13:32 624如下,可以打出带依赖包的jar package.ba ... -
打印线程详细信息并按CPU占用排序
2014-05-28 17:20 704好久没来写了,不过太好用了,记录下 #!/bin/ksh ... -
java hashCode详解
2013-05-17 21:12 2781=============================== ... -
PO、DO、VO的区别
2013-05-17 16:53 2627Rational Mapping( ... -
java.util.concurrent 包
2013-04-03 11:09 1035java.util.concurrent 包含许多线程安全、 ... -
BTrace使用简介
2013-03-27 21:05 790很多时候在online的应用出现问题时,很多时候我们需要知道 ... -
BTrace使用总结
2013-03-27 21:01 1068一、背景 在生产环境中可能经常 ... -
java Singleton 的使用详解
2013-03-21 16:15 792概念: 在Java应用程序中,一个类Class只有一个实 ... -
java中的lock和synchronized
2013-03-21 10:04 9081、ReentrantLock 拥有Synchronized相 ... -
Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制
2013-03-21 09:58 661多线程和并发性并不是什么新内容,但是 Java 语言设计中的 ... -
Java5中lock
2013-03-20 11:24 948说明:Java多线程相关相关几篇文章转自http://lav ... -
栈与堆的困惑--java内存解析
2013-03-19 19:12 664----对这两个概念的不明好久,终于找到一篇好文,拿来共享1. ... -
Java内存之"栈"与"堆"
2013-01-30 20:13 718引用: http://1615926449.iteye.co ... -
java 基本数据类型转换迷惑
2012-11-26 21:31 1418转自:http://jiangzhengjun.itey ... -
velocity 循环set null
2012-08-03 20:10 1043今天很不幸又看到中站一个故障,又是因为在velocity模板中 ... -
Hash碰撞/ Hash Collision
2012-01-10 19:30 1322最近一个Hash Collision DoS(Hash碰撞的拒 ... -
java回调函数的超形象例子
2011-10-20 10:20 1100无意间看到这个哥们的牛X解释: 下面举个通俗的例子: ... -
JDK中的URLConnection参数详解
2011-09-03 18:36 694JDK中的URLConnection参数详解 针对JD ...
相关推荐
75.java成员变量与局部变量.zip75.java成员变量与局部变量.zip75.java成员变量与局部变量.zip75.java成员变量与局部变量.zip75.java成员变量与局部变量.zip75.java成员变量与局部变量.zip75.java成员变量与局部变量....
Java 面向对象中的两类 变量 : 成员变量和局部变量
Java性能优化技巧集锦 很全 。。。 1.1 不用new关键词创建类的实例 1.2 使用非阻塞I/O 1.3 慎用异常 1.4 不要重复初始化变量 1.5 尽量指定类的final修饰符 1.6 尽量使用局部变量 1.7 乘法和除法 二、...
Java性能优化的45个细节 1.尽量在合适的场合使用单例 2.尽量避免随意使用静态变量 ...
全局变量、局部变量、静态全局变量、静态局部变量的区别
局部变量:在方法内或者方法声明处 在内存中的位置不同 成员变量:在堆内存中 局部变量:在栈内存中 初始化值不同 成员变量:有默认的初始化值 局部变量:没有初始化值,必须手动初始化 生命周期不同 成员...
JAVA最佳性能优 化JAVA优化技巧 类的方法内联,方法的同步及局部变量的使用 创建类的实例优化策略 建立对象池提升性能策略 JAVA垃圾回收机制及引用优化策略
通过代码的运行,并理解代码,明白C中的局部变量与本地变量的区别
Java性能优化: 1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 控制资源的使用,通过线程同步...
如何获得局部变量名 关于System.out.println("abc="+abc);的优化 尽管eclipse提供了Debug工具,还是习惯写System.out.println("abc="+abc); 经常写这样的语句,总感觉变量abc每次写两遍,有些重复。 网上找了很多资料...
java局部变量
VB 局部变量举例 VB 局部变量举例 VB 局部变量举例
在JavaScript中,我们应该尽可能的用局部变量来代替全局变量,这句话所有人都知道,可是这句话是谁先说的?为什么要这么做?有什么根据么?
静态全局变量,静态局部变量,全局变量,局部变量静态全局变量,静态局部变量,全局变量,局部变量
1、局部变量能否和全局变量重名? 答:能,局部会屏蔽全局。要用全局变量,需要使用"::" ; 局部变量可以与全局变量同名, 在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器 而言...
Java优化编程(第2版)通过丰富、完整、富有代表性的实例,展示了如何提升Java应用性能,并且给出了优化前与优化后的Java应用程序的性能差别,以实际的实例与数字告诉你,为什么不可以这么做,应该怎么做,深入分析...
block,局部变量,全部变量,static的静态变量关系
变量可以分为全局变量、静态全局变量、静态局部变量和局部变量 按存储区域分:全局变量、静态全局变量和静态局部变量都存放在内存的全局数据区,局部变量存放在内存的栈区 按作用域分:全局变量在整个工程文件内都...
主要涉及了java中的局部变量和全局变量,就二者的含义、生存时间和创建位置作了介绍,需要的朋友可以参考下。
类变量是类中的静态变量,是用static修饰的变量;实例变量就是类中的成员变量,没有用static修饰的。 类变量是所有对象公用的,实例变量是对象私有的;当一个对象将类变量进行修改...局部变量,即定义在方法内部的变量。