其他
终于,有大佬通过JS代码讲清楚了Java中的逃逸分析...
来源:http://1t.click/anZy
Js代码
var n=999;
function f1(){
alert(n);
}
f1(); // 999
function f1(){
var n=999;
}
alert(n); // error
Js代码
function f1(){
n=999;
}
f1();
alert(n); // 999
如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
Js代码
function f1(){
n=999;
function f2(){
alert(n); // 999
}
}
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
function f1(){
n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
f1函数就是河,而f2函数就是河里的鱼,鱼的新陈代谢的产物就是其返回的结果,同样是不是类似于我们和空气的关系,吸进去的是氧气,返回的结果的是二氧化碳
# 由域联系到的逃逸分析
给全局变量赋值,发生逃逸;
方法的返回值,会发生逃逸
实例的引用传递,也会发生逃逸
通过逃逸分析,我们可以对jvm的这个过程进行优化,即对栈的重新分配,首先需要分析并找到这期间为发生逃逸的变量,将变量类的实例化直接在栈里发生,即不需要经过堆,分配完成后,继续在栈内执行,最后线程结束,栈空间被回收,同样,局部变量也会跟着栈消失,优化后和优化前的区别就是减少了临时对象在堆内的分配数量(即未逃逸的对象无须堆内创建)。
逃逸分析不能在静态编译时进行,必须在JIT里完成,因为我们在正常的代码过程中运行时会通过动态代理改变一个类的行为,这时就无法得志类已经变化。
举个例子,比如一个方法的返回值是void,方法内部有对象的创建,如:
public void use_a()
{ A a=new A();
//a.xx();
...
a=null
}
JIT在编译时,假如能分析出这种代码,那么非逃逸的对象的创建和回收就可以在栈上进行,从而大大提高Java的运行性能。
往往我们会碰到这个情况,就是方法内调用另一个方法,有点类似js的闭包了吧,这时就要进行内联分析,因为往往一些对象在被调用过程中创建并返回给调用,比如上面的a.xx(),假如有返回值赋值给另外的局部变量的过程(这下应该好理解这个概念了吧),在调用过程中使用完就被销毁回收了,其实都清楚程序的执行过程是自上而下的,其实函数的调用也无非是把一段代码嵌入到另一段代码里顺序执行处理而已,说白了两个方法内联成一个方法体,而这个也是我们平常方法重构的一个过程,这种原来通过返回传递的对象就变成了方法内的局部对象,也就变成了非逃逸对象了,这样,这些对象就可以在同一个栈上进行分配了。
Java7已经开始支持对象的栈分配和逃逸分析,这样除了上述的优化外还会带来 同步消除和矢量替代,关于这两个可以查阅相应资料
这里对方法逃逸再贴两段代码,方便大家加深认识:
public static StringBuffer craeteStringBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb;
}
甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,称为线程逃逸。
public static String createStringBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
Js代码
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
我去!你竟然不知道Spring MVC中有现成的WebSocket组件...
咱们团队的SQL水平竟如此糟糕,一条SQL执行时间高达5分钟...
同时,分享一份Java面试资料给大家,覆盖了算法题目、常见面试题、JVM、锁、高并发、反射、Spring原理、微服务、Zookeeper、数据库、数据结构等等。