从JVM角度看,有这几种优化手段:java
栈上分配:
同步省略
标量替换
这几个优化手段须要JVM配置以外,写代码时仍是须要配合的点,要不JVM优化也不会起做用,拜拜提供了优化手段而你不用面试
代码优化点太多了,我觉淂仍是叉开来好些好理解一些......post
栈上分配具体内容看:JVM 面试题【中级】,我就再也不写一遍了性能
方法内部变量写的好一些,仔细一些以实现栈上分配的确有很大优点,这里跑个例子测试
public class Max {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
newValue();
}
long endTime = System.currentTimeMillis();
System.out.println("Time:" + (endTime - startTime));
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void newValue() {
Dog dog = new Dog();
}
}
复制代码
-Xms256m -Xmx256m -XX:-DoEscapeAnalysis -XX:+PrintGCDetails
[GC (Allocation Failure) [PSYoungGen: 65536K->761K(76288K)] 65536K->769K(251392K), 0.0016895 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 66297K->713K(76288K)] 66305K->721K(251392K), 0.0023094 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Time:91
复制代码
-Xms256m -Xmx256m -XX:+DoEscapeAnalysis -XX:+PrintGCDetails
Time:7
复制代码
你们别看测试用例方法是执行1000万次,就意味没有实际意义啦,你们写的程序,分分钟你觉得方法执行的少吗,能不能作到栈上分配堆性能是及其有意思的,差距你们都看到了吧优化
神转折来啦 (/// ̄皿 ̄)○~ 这是《深刻理解JVM虚拟机里的原话》
spa
逃逸分析的技术99年就出现了,一直到JDK1.6 Hotspot 才开始支持初步的逃逸分析,即使到如今这项技术仍未成熟,还有很大的改进余地。不成熟的缘由是逃逸分析的计算成本很是高,甚至不能保证带来的性能优点会高于计算成本,在实际应用中,尤为是大型应用中反而发现逃逸发分析可能出现不稳定的状态。直到JDK7时才默认开启这项技术,服务模式的java程序才支持3d
上面例子效果明显,更多缘由是由于下面会说的标量替换
,没看到内存快照嘛,即使开启逃逸分析以后,Dog对象在堆内存中仍是有很是多的对象存在,这和理论差距仍是满大的日志
懒得打字了,你们看图吧: code
典型的例子:
public void test() {
Dog dog = new Dog();
synchronized (dog) {
System.out.println(dog);
}
}
复制代码
对于上面这个方法,JIT 动态编译器虽然会帮咱们自动把锁消除了,可是在这是在运行阶段才会优化的,编译成字节码时仍是能看到锁指令的
另外虽然有JIT优化,可是相比咱们直接不写锁,优化以后的性能仍是不如的,你们最好仍是这样写,性能更好一些:
public void test() {
Dog dog = new Dog();
System.out.println(dog);
}
复制代码
java 中:
标量:
是指一个没法再被分解成更小的数据的数据,好比基础数据类型聚合量:
相对的就是那些还能够再分解的,好比对象就是-XX:+EliminateAllocations
JDK7开始默认是开启的在JIT阶段,通过逃逸分析后,若是方法内对象符合栈上分配的规则,那会这个对象在栈上就会以标量的形式存储,能够进一步节省分配对象的操做
好比一个对象:
public class Dog extends Max {
public int age = 10;
public String name = "AA";
}
复制代码
通过标量替换后,一个Dog对象会以这种方式存储在局部变量表里:
public void test() {
// 一个 Dog 对象会变成下面这样
int age = 10;
String name = "AA";
}
复制代码
标量替换为栈上分配提供了很好的基础 (⊙﹏⊙)
标量替换你要是在 JVM 配置里面关了,那栈上分配就无论用了,标量替换、栈上分配
这2个必须都得设置才能起做用
PS:想骂娘,深度越深的技术,只是点都是这样拔出萝卜带出泥,一茬接一茬,应接不暇,越看越晕,要是资料再补全,跳着来,尼玛想死的心都有 (〃>目<)