java虚拟机-虚拟机的前世今生

每个线程使用,线程在运行时,在执行每个方法的时候回打包成一个栈帧,存储了局部变量表,操作数栈,动态链接,方法出口等信息,然后放入栈。每个时刻正在执行的当前方法就是虚拟机栈顶额栈帧。方法的执行就对应着栈帧在虚拟机栈中入栈和出栈的过程。

栈帧大小缺省为1M,可用参数-Xss调整大小,例如:-Xss256k

几乎所有的对象对分配在这,也就是垃圾回收发生的主要区域,可用以下参数调整:

-Xms: 堆的最小值 -Xmx: 堆的最大值 -Xmn: 新生代的大小 -xx:NewSize: 新生代最小值 -xx:MaxSize: 新生代最大值 如:-Xmx256m

方法去/永久代

用于存储已经被虚拟机加载的类信息,常量(“zdy”,“123” 等),静态变量等数据;可以用以下参数调整:

jdk1.7及以前:-XX:PermSize;-XX:MaxPermSize; jdk1.8以后: -XX:MetaspaceSize; -XX:MaxMetaspaceSize jdk1.8以后大小就只受本机总内存的限制 如:-XX:MaxMetaspaceSize=3M

直接内存

不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域;如果使用NIO,这块区域会被频繁使用,在java堆内可以使用directByteBuffer对象直接引用并操作; 这块内存不受java堆大小限制,但受本机总内存的限制,可以通过-XX:MaxDirectMemorySize来设置(默认与堆内存最大值一样),所以也会出现oom(内存溢出)异常

各个版本内存区域的变化
  • jdk1.6: 运行时常量池在方法区中 image.png

  • jdk1.7: 运行时常量池在堆中 image.png

  • jdk1.8: 运行时常量池在堆中,方法区变成元空间 image.png

  • 站在线程角度来看

image.png

深入辨析堆和栈

功能

  • 一栈帧的凡是存储方法调用的过程,并存储方法调用的过程中基本数据类型的变量(int,short,long,byte,float,double,boolean,char等)以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放;
  • 而堆内存是用来存储java中的对象。无论是变量,还是类变量,他们指向的对象都是存储在堆内存中;

线程独享还是共享

  • 栈内存归属于单线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
  • 堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问

空闲大小

  • 栈内存要远远小于堆内存
栈上分配
  • 虚拟机提供的一种优化技术,基本思想是:对于线程私有的对象,将它打撒分配在栈上,而不是分配在堆上。好处是对象跟着方法调用自行销毁,不进行垃圾回收,提高新能
  • 栈上分配需要的技术基础,逃逸分析。逃逸分析的目的判断对象的作用域是否会逃逸出方法体。$\color{red}{注意,任何可以在多线程之间共享对象,一定都属于逃逸对象}$。

代码如下

package com.enjoy.cap1;

public class StackAlloc {

    public static class User{

        public int id = 0;
    }

    public static void alloc() {

        User user = new  User();
        user.id = 5;
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            alloc();
        }
        long end = System.currentTimeMillis();
        System.out.println((end-start)+"ms");
    }

}

编译变量环境设置

-server -Xmx10m -Xms10m -XX:+PrintGC -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-UseTLAB

运行结果:

[GC (Allocation Failure)  2047K->680K(9728K), 0.0007156 secs]
4ms

不是用逃逸分析:

-server -Xmx10m -Xms10m -XX:+PrintGC -XX:-DoEscapeAnalysis -XX:+EliminateAllocations -XX:-UseTLAB

[GC (Allocation Failure)  2840K->792K(9728K), 0.0002678 secs]
[GC (Allocation Failure)  2840K->792K(9728K), 0.0002149 secs]
[GC (Allocation Failure)  2840K->792K(9728K), 0.0003496 secs]
1231ms

从实验找那个两个时间来看,使用逃逸分析比没有使用逃逸分析要快1227ms

  • 如何启用线上分配

-server : jvm运行的模式之一,server模式才能进行逃逸分析,jvm运行模式还有 mix/client -Xmx10m 和 -Xms10m :堆的大小 -XX:+DoEscapeAnalysis :启动逃逸分析(默认为打开) -XX:+EliminateAllocations :标量替换(默认为打开) -XX:-UseTLAB 关闭本地线程分配缓冲 TLAB: ThreadLocalAllocBuffe,具体解释参见下文《虚拟机中的对象---对象的分配----2)》

  • 对栈上分配发生影响的参数就是三个。-server,-XX:DoEscapeAnalysis和-XX:+EliminateAllocations,任何一个发生变化都不会发生栈上分配,因为启动逃逸分析和标量替换默认是打开,所有,在我们例子中,JVM的电参数只用-server一样可以有栈上替换的效果
元数据空间

受本机内存的影响

直接内存

受本机内存的影响

本文由博客一文多发平台 OpenWrite 发布!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值