Table of Contents generated with DocToc

笔记来源:图灵学院

一、java虚拟机概述

  1. java虚拟机用于将字节码文件.class转化为不同操作系统上的机器码

  1. java虚拟机的内存模型


二、栈内存解析

2.1 概述

java虚拟机为每一个java线程分配一个栈内存空间,存放变量

public class Math{
public static final int initData = 666;//常量存储在方法区
public int compute() { //一个方法对应一块栈帧内存区域
int a=1;
int b=2;
int c = (a+b)*10;
return c;
}
public static void main(String[] args){
Math math = new Math();
math.compute();
}
}

a,b,c 保存在main线程的compute()栈帧中

2.2 栈帧内部结构

学习栈帧内部结构前,我们首先要阅读字节码文件。

javac Math.java
javap -c Math.class > Math.txt

打开生成的Math.txt,可以看到反汇编后的代码如下:

Compiled from "Math.java"
public class jvm.Math {
public static final int initData; public jvm.Math();
Code:
0: aload_0
1: invokespecial #12 // Method java/lang/Object."<init>":()V
4: return public int compute();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 10
9: imul
10: istore_3
11: iload_3
12: ireturn public static void main(java.lang.String[]);
Code:
0: new #1 // class jvm/Math
3: dup
4: invokespecial #25 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #26 // Method compute:()I
12: pop
13: return
}
2.2.1 我们来解析一下compute()里面的代码:
public int compute() { //一个方法对应一块栈帧内存区域
int a=1;
int b=2;
int c = (a+b)*10;
return c;
} //======================================= public int compute();
Code:
0: iconst_1 //将常量1压入操作数栈
1: istore_1 //将int类型的值存入局部变量1 -- a
2: iconst_2 //将常量2压入操作数栈
3: istore_2 //将int类型的值存入局部变量2 -- b
4: iload_1 //从局部变量1装载int类型的值
5: iload_2 //从局部变量2装载int类型的值
6: iadd //1+2
7: bipush 10
9: imul //*10
10: istore_3 //将int类型的值存入局部变量3 -- c
11: iload_3 //装载c的值
12: ireturn

赋值过程:

装载,执行过程(操作数栈:临时存储需要操作的值):

2.2.2 main函数内存区域

​ main中存储了一个math对象的指针,指向堆(堆中有为这个对象开辟的内存空间):

三、本地方法栈

早期 JAVA 需要与C/C++进行交互,所以用本地方法栈存储C/C++方法

四、堆

首先我们看看堆的结构:

​ 堆假设只有600M的话,那么年轻代占了1/3,也就是200M,老年代占了2/3。最开始的时候,对象都存放在Eden伊甸区)中。

​ 当Eden区装满时,则字节码执行引擎开启一个线程,运行minor gc,扫描伊甸区中的对象,如果对象被引用了,则在s0区中复制一份,否则留在Eden中,被垃圾回收机制清理。

​ 其他区域也是类似的处理(在Eden,s0,s1中移动时,“年龄“会加大,当达到15时,会转入老年区,controller、service、bean、数据库持久层、缓存都是常见的老年区对象):

​ 当老年代区放满后,字节码执行引擎开启一个线程,运行full gc,对所有区域进行垃圾回收,减少堆的空间,但是老年区被引用的对象还是不会被回收,所以当老年区再次被放满溢出时,会触发OutOfMemoryError的异常,即java堆不够用了。

扩展:STW【stop the world】,当 JVM 调用gc清理堆时,会暂停掉所有用户程序,比如电商购物时,点击按钮后通常会卡顿一下

垃圾回收,减少堆的空间,但是老年区被引用的对象还是不会被回收,所以当老年区再次被放满溢出时,会触发OutOfMemoryError的异常,即java堆不够用了。

扩展:STW【stop the world】,当 JVM 调用gc清理堆时,会暂停掉所有用户程序,比如电商购物时,点击按钮后通常会卡顿一下

所以 JVM 调优就是:尽量想方设法减少 STW 时间

图灵学院笔记-java虚拟机底层原理的更多相关文章

  1. Java虚拟机工作原理

    Java虚拟机工作原理 首先我想从宏观上介绍一下Java虚拟机的工作原理.从最初的我们编写的Java源文件(.java文件)是如何一步步执行的,如下图所示,首先Java源文件经过前端编译器(javac ...

  2. (前篇:NIO系列 推荐阅读) Java NIO 底层原理

    出处: Java NIO 底层原理 目录 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3. 同步 ...

  3. 理解java容器底层原理--手动实现HashMap

    HashMap结构 HashMap的底层是数组+链表,百度百科找了张图: 先写个链表节点的类 package com.xzlf.collection2; public class Node { int ...

  4. Java面试底层原理

    面试发现经常有些重复的面试问题,自己也应该学会记录下来,最好自己能做成笔记,在下一次面的时候说得有条不紊,深入具体,面试官想必也很开心.以下是我个人总结,请参考: HashSet底层原理:(问了大几率 ...

  5. Java虚拟机 - 结构原理与运行时数据区域

    http://liuwangshu.cn/java/jvm/1-runtime-data-area.html 前言 本来计划要写Android内存优化的,觉得有必要在此之前介绍一下Java虚拟机的相关 ...

  6. 阅读笔记--java内存模型原理

    在阅读本篇文章之前,我所理解的和上网了解到的java内存模型原理如下: 不同架构的物理计算机可以有不一样的内存模型,Java 虚拟机也有自己的内存模型.Java 虚拟机规范中试图定义一种 Java 内 ...

  7. Java虚拟机工作原理详解 ( 二 )

    首先这里澄清两个概念:JVM实例和JVM执行引擎实例,JVM实例对应了一个独立运行的Java程序,而JVM执行引擎实例则对应了属于用户运行程序的线程:也就是JVM实例是进程级别,而执行引擎是线程级别的 ...

  8. Java虚拟机工作原理详解 (一)

    一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘当中.然后你在命令行中输入 javac YourClassNam ...

  9. Java虚拟机工作原理详解

    原文地址:http://blog.csdn.net/bingduanlbd/article/details/8363734 一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了 ...

随机推荐

  1. 尚学堂 215 在java中执行JavaScript代码

    package com.bjsxt.test; import java.io.FileReader; import java.net.URL; import java.util.List; impor ...

  2. Python3-multiprocessing模块-多进程

    Python3中的multiprocessing模块是一个与threading模块类似,提供生成进程的API 多进程multiprocessing模块允许程序员充分利用给定机器上的多个CPU(处理器) ...

  3. DNS篇(详解DNS)

    *文章来源:https://blog.egsec.cn/archives/601 *本文将主要说明:本文主要叙述什么是DNS.域名的层级.DNS 解析过程.DNS的缓存时间.DNS 的记录类型.DNS ...

  4. liunx中组合查询的命令

    今天无聊,把以前的liunx命令拿过练练,尤其是一些组合命令并带有逻辑的.这里的script是一个文件夹. 1.查看一个文件的最后3行的第一行. [root@localhost home]# tail ...

  5. 平时自己常用的git指令

    增删改查 创建标签 $ git tag -a v1.4 -m 'my version 1.4' 用 -a (译注:取 annotated 的首字母)指定标签名字即可 -m 选项则指定了对应的标签说明 ...

  6. MongoDB快速入门教程 (3.2)

    3.2.索引 索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,建立索引,通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条 ...

  7. Nginx配置upstream实现负载均衡1

    如果Nginx没有仅仅只能代理一台服务器的话,那它也不可能像今天这么火,Nginx可以配置代理多台服务器,当一台服务器宕机之后,仍能保持系统可用.具体配置过程如下: 1. 在http节点下,添加ups ...

  8. 浅谈auth模块

    目录 auth模块 什么是Auth模块 auth模块的常用方法 用户注册 扩展默认的auth_user表 auth模块 什么是Auth模块 ​ auth模块是对注册登录认证注销修改密码等方法的一种封装 ...

  9. 如何嵌套一个网页html到另一个html中

    在常规网页开发中(单页应用除外哈),经常会遇到把一些通用内容的页面集中到一个页面中,需要使用这些页面只需要包含引入即可,这样有利于维护和修改,当通用页面修改时只需更改一个文件就可以了,不需要每个文件单 ...

  10. plus.runtime.quit()是个好函数

    对于H5+APP开发,应用的生命周期监听函数里是对应用行为的监控,但是并不对应用执行退出或重启操作.相关操作还是要使用mui