- 浏览: 287043 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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 1374http://www.blogjava.net/xylz/ar ... -
问题排查记录-linux
2016-08-05 12:02 854### 以下所有命令都要先sudo su admin ... -
打完整含依赖包的jar包
2015-04-10 13:32 667如下,可以打出带依赖包的jar package.ba ... -
打印线程详细信息并按CPU占用排序
2014-05-28 17:20 739好久没来写了,不过太好用了,记录下 #!/bin/ksh ... -
java hashCode详解
2013-05-17 21:12 2822=============================== ... -
PO、DO、VO的区别
2013-05-17 16:53 2773Rational Mapping( ... -
java.util.concurrent 包
2013-04-03 11:09 1076java.util.concurrent 包含许多线程安全、 ... -
BTrace使用简介
2013-03-27 21:05 836很多时候在online的应用出现问题时,很多时候我们需要知道 ... -
BTrace使用总结
2013-03-27 21:01 1117一、背景 在生产环境中可能经常 ... -
java Singleton 的使用详解
2013-03-21 16:15 834概念: 在Java应用程序中,一个类Class只有一个实 ... -
java中的lock和synchronized
2013-03-21 10:04 9451、ReentrantLock 拥有Synchronized相 ... -
Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制
2013-03-21 09:58 693多线程和并发性并不是什么新内容,但是 Java 语言设计中的 ... -
Java5中lock
2013-03-20 11:24 998说明:Java多线程相关相关几篇文章转自http://lav ... -
栈与堆的困惑--java内存解析
2013-03-19 19:12 698----对这两个概念的不明好久,终于找到一篇好文,拿来共享1. ... -
Java内存之"栈"与"堆"
2013-01-30 20:13 758引用: http://1615926449.iteye.co ... -
java 基本数据类型转换迷惑
2012-11-26 21:31 1506转自:http://jiangzhengjun.itey ... -
velocity 循环set null
2012-08-03 20:10 1101今天很不幸又看到中站一个故障,又是因为在velocity模板中 ... -
Hash碰撞/ Hash Collision
2012-01-10 19:30 1363最近一个Hash Collision DoS(Hash碰撞的拒 ... -
java回调函数的超形象例子
2011-10-20 10:20 1195无意间看到这个哥们的牛X解释: 下面举个通俗的例子: ... -
JDK中的URLConnection参数详解
2011-09-03 18:36 726JDK中的URLConnection参数详解 针对JD ...
相关推荐
Java性能优化是提升Java应用程序效率的关键技术,涵盖了内存管理、代码优化、I/O处理等多个方面。以下是一些关键的性能优化策略: 1. **对象创建与克隆**:使用`new`关键字创建对象时,会调用构造函数链,这可能...
### Java性能优化技巧集锦 #### 一、通用篇 **1.1 不用new关键词创建类的实例** - **背景**: 使用`new`关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。这种方法可能会消耗较多资源。 - **优化...
4. **使用局部变量**:尽可能减少方法的参数,避免方法间共享对象,提高局部性原理的利用。 5. **避免空对象检查**:如果可能,使用Optional类来封装可能为null的对象,减少显式的null检查。 6. **使用equals()与...
1. **字段值的获取**:从 `ResultSet` 获取字段值时,应尽可能使用与字段类型相匹配的获取方法,避免类型转换带来的额外开销。 2. **字段选择**:只检索必要的字段,避免使用 `SELECT * FROM tableName` 类型的语句...
在Java性能优化中,合理使用单例模式可以带来以下优势: 1. **控制资源使用**:通过线程同步来控制资源的并发访问,尤其是在多线程环境下,可以有效减少资源竞争,提高资源利用率。 2. **控制实例产生**:减少不必...
通过以上分析,我们可以看到Java性能优化不仅涉及到集合操作和反射机制的巧妙运用,还涵盖了对象创建的优化和基础编程技巧。对于有经验的Java开发者来说,深入理解并实践这些方法,将显著提升代码质量和系统性能。在...
以下是一些2022年仍然适用的Java性能优化技巧: 1. **避免使用`new`关键字创建对象** 使用`new`创建对象时,会执行构造函数链,消耗额外的时间。如果对象实现了`Cloneable`接口,可以考虑使用`clone()`方法,它不...
下面将详细讨论一些通用的Java性能优化技巧。 1.1 避免使用`new`关键字创建对象 创建对象时,构造函数链中的所有构造函数都会被调用,这可能导致不必要的开销。如果对象实现了`Cloneable`接口,可以使用`clone()`...
### Java性能优化技巧详解 #### 一、通用篇:适用多数Java应用的优化策略 **1.1 使用`clone()`方法代替`new`** 在Java中,通过`new`关键字创建对象实例时,会自动调用类的所有构造函数,这可能会带来额外的开销。...
### Java性能优化借鉴 #### 一、合理使用单例模式 单例模式是软件开发中常用的模式之一,它确保一个类只有一个实例,并提供一个全局访问点。在Java中使用单例模式可以有效控制资源的使用,减少不必要的实例化操作...
Java性能优化是提升应用程序效率的关键,特别是在开发高性能网站时,每一点优化都能带来显著的性能提升。以下是一些Java性能优化的关键点: 1. **合理分配对象空间**:在Java中,很多类如`Vector`有默认的内存分配...
尽可能地使用局部变量,因为局部变量存储在栈中,相对于堆内存中的对象来说,访问速度更快。而且局部变量不需要垃圾回收器来回收,能够减轻垃圾回收的压力。 4. 及时关闭流 在进行数据库连接、文件IO等操作时,应当...
本篇将基于《java time and space performance tips》一书中的知识,结合提供的个人测试代码,深入探讨Java性能优化的策略。 1. **避免不必要的对象创建** - 在Java中,频繁的对象创建和垃圾回收会增加运行时的...
栈中的变量访问速度快于堆中的对象,因此尽可能使用局部变量而非对象实例可以提高程序执行效率。 #### 6. 装箱与拆箱 装箱是指将基本数据类型转换为对应的包装类,而拆箱则是相反的过程。频繁地进行装箱和拆箱操作...
8. **使用局部变量**:尽可能将变量声明为局部变量,减少作用域,提高效率。 9. **谨慎使用反射**:反射虽然灵活,但性能开销大,尽量避免在性能敏感区域使用。 10. **避免在循环中调用方法**:如果可能,将方法...