Java虚拟机浅浅析

2020-04-07  本文已影响0人  瑜小贤

Java SE体系架构

虚拟机的发展

未来的Java技术

运行时数据区域

  1. 定义
    Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域
  2. 类型

程序计数器

是指向当前线程正在执行的字节码指令地址(行号)(面试点)

为什么需要程序计数器(面试点)

  • Java是多线程的,意味着存在线程切换
  • 确保多线程情况下的程序正常执行

运行时数据区:栈

栈结构
数据结构
特点(面试点)
为什么JVM要使用栈(面试点)

因为非常符合Java中方法间的相互调用

public class StackFilo {
    public static void main(String[] args)
    {
        A();  //A()->B()->C()
    }
    public static  void A(){
        System.out.println("A开始");
        //此处省略100行代码
        B();//调用B方法
        System.out.println("A结束");
    }
    public static void B(){
        System.out.println("B开始");
        //此处省略100行代码
        C();//调用C方法
        System.out.println("B结束");
    }
    public static void C(){
        System.out.println("C开始");
        //此处省略100行代码
        System.out.println("C结束");
    }
}

//log
A开始 
B开始
C开始
C结束
B结束
A结束
虚拟机栈
  • 局部变量表
  • 操作数栈
  • 动态连接
  • 返回地址
  • -Xss JDK 1.8默认1M)
  • 只入栈不出栈,会栈溢出(常见于循环调用、递归调用处理不当)
public class JavaStack {
/*    public static class User{
        public int id = 0;
        public String name = "";
    }*/
    //常量
    final  String Fs ="常在河边走,哪有不湿鞋";
    //静态变量
    static String Ss ="以静制动";
    //次数
    int count =0 ;
    //King老师出差
    public void king(int money){
        //13号技师
        Object tech13 = new Object();
        //调用一次13号服务
        tech13.hashCode();
        int i;
        money = money -100; //花费100
        count++;
        //if(count ==2000) return;
        king(money);
     }
    public static void main(String[] args)throws Throwable {
        JavaStack javaStack = new JavaStack();
        try {
            javaStack.king(10000);
        }catch (Throwable e){
            //输出异常时循环的次数
            System.out.println("栈异常!调用方法(king)的次数():"+javaStack.count);
            throw e;
        }
    }
}
虚拟机栈的执行过程演示.png
本地方法栈

线程共享区域

方法区

Java堆

堆的大小参数设置

  • -Xmx 堆区内存可被分配的最大上限
  • -Xms 堆区内存出事内存分配的大小

直接内存

不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域

深入辨析堆和栈

功能

线程独享还是共享

空间大小

虚拟机中对象

对象的内存布局

对象的访问定位

虚拟机优化技术--逃逸分析

逃逸分析

逃逸分析是目前JVM中比较前沿的优化技术,它不是直接优化手段而是为其他优化手段提供依据的分析技术
逃逸分析的基本行为就是分析对象动态作用域。

栈上分配

99% 对象都在堆上分配
1% 对象可能在创建时经逃逸分析,在栈上分配
如果是栈上分配,就不需要垃圾回收了,会随着线程的结束而消亡

public class StackAlloc {

    public static class User{
        public int id = 0;
        public String name = "";
    }

    
    public static void alloc() {
        User u = new User();  //Object  在堆上分配的() ,有逃逸分析的技术 ,在栈中分配的
        u.id = 5;
        u.name = "King";
    }

    public static void main(String[] args) {
        long b = System.currentTimeMillis(); //开始时间
        for(int i=0;i<100000000;i++) {//一个方法运行1亿次()
            alloc();
        }
        long e = System.currentTimeMillis(); //结束时间
        System.out.println(e-b);//打印运行时间:毫秒
    }

}

牵扯到的JVM参数

-XX:+DoEscapeAnalysis:启用逃逸分析(默认打开)-XX:-DoEscapeAnalysis(关闭)
XX:DoEscapeAnalysis
-XX:+EliminateAllocations:标量替换(默认打开)
-XX:+UseTLAB 本地线程分配缓冲(默认打开)
-XX:+PrintGC(打印垃圾回收过程)

上一篇 下一篇

猜你喜欢

热点阅读