狂神说JVM学习笔记

JVM是运行在操作系统上的一个虚拟机环境,示例如下图
在这里插入图片描述
运行时的整体流程如下图:
在这里插入图片描述
其中,虚拟机栈、本地方法栈、程序计数器是线程私有,方法区(元空间)、堆是线程共有。
当一个类加载后,先加载main方法,此时main方法被压在栈底,由main方法所引用的方法依次堆放在上一个位置。程序计数器用于存储下一个字节码的内存地址,占用空间很少。
堆存放的有实例对象、数组、字符串常量池等,例如:

Hello hello = new Hello();
int[] array = {1, 2, 3};
String str = "Hello";

方法区:存储的是基本数据类型、运行时常量池
由于栈存放的是方法,不会有垃圾(如果有垃圾那栈直接就卡住了),程序计数器存放的是下一个字节码的内存地址,那垃圾回收只能在堆里进行(GC),所以99%都是在堆里垃圾回收。

在这里插入图片描述
首先一个类进来后,编译为Car.class,经过类加载器,加载初始化对象变成一个个实例car1、car2,名字在栈里头,对应一个个内存地址指向堆里。实例放在堆中,存放属性等。

反向怎么导呢? 可以使用.getClass()方法找到对象,再使用.getClass Loader()找到对应的类加载器。

加载器有以下几种:
在这里插入图片描述
类加载过程如下:
在这里插入图片描述

本地方法接口(JNI)为了调用本地方法库,扩展java的使用,融合不同的编程语言为Java所用
在这里插入图片描述

在这里插入图片描述
当一个对象被加载后,堆里会存在字符串常量池,如果实例给stringname赋值,那么就存放在栈内存放地址所指向的实例中,如果没有,那么直接从堆里的字符串常量池中取出"qinjiang"。(java8之后字符串常量池从方法区的运行时常量池分离出来)

public class Test{
	private int a;
	private stringname = "ginjiang";
	public static void main(string[]args){
		Testtest1 = new Test();
}

方法区

Method Area 方法区
方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间:
静态变量、常量、类信息 (构造方法、接口定义)、运行时的常量池存在方法区中,但是 实例变量存在堆内存中,和方法区无关
静态变量、常量:static final
类信息(构造方法、接口定义):Class文件,包括类的属性方法注解修饰符
运行时的常量池:常量池


在这里插入图片描述
栈的运行原理:通过栈帧对每一个方法进行调用
在这里插入图片描述

栈里存放方法里局部变量的值(如果是基本数据类型,引用和值都存储在栈里)存放在局部变量表中
在这里插入图片描述
如果时局部变量表中要存储的是字符串,那就是存储堆里面字符串常量池的地址,如果是存储的值,那就把值从方法区的运行时常量值中取出来,放进去(放的是值而不是地址),只有运行时才会存储,如果不运行局部变量表里就没有东西
相较而言,堆里存放的是实例以及成员变量,数组、字符串常量池
如果方法产生循环引用,就会导致栈溢出——StackOverflow Error

目前所用的主流jvm为hotspot,堆内存主要分为:
新生区(伊甸园区)
老年区
永久区
在这里插入图片描述
垃圾回收,主要是在伊甸园区和养老区
一般只会存在栈内存满,如果是堆内存满,就会出现OOM java.lang.OutOfMemoryError: java heap space
在JDK8以后,永久存储区改了个名字(元空间);

新生区:
类诞生、成长、甚至死亡的地方
伊甸园区:所有新对象都是在这个new出来的。——一次垃圾回收后它会进入幸存区(0,1)

老年区:
经过多次轻GC后来到的区域,

真理:99%的对象都是临时对象!

永久区:
这个区域常驻内存,用来存放JDK自带的Class对象,interface元数据,存储的是java运行时的一些环境或类信息
不存在垃圾回收!
关闭JVM就会释放这个区域的内存

  • JDK1.7之前都是永久代,存放在方法区中,常量池在方法区
  • JDK1.8之后是元空间,没有永久代,常量池在元空间
    在这里插入图片描述
  1. 内存溢出
      内存溢出 OOM (out of memory),是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。

  2. 内存泄漏
      内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。最终的结果就是导致OOM
      内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。

GC算法:引用计数法、标记整理法、标记清除法、复制法
引用计数法
在这里插入图片描述
复制算法
每次在幸存区from和to区两个之间移动,就是复制算法,把其中有对象的复制到另外一个,然后清空,此时这个区域没有对象就是to区,然后继续GC
谁空谁是to区
在这里插入图片描述
在这里插入图片描述
好处:没有什么内存碎片
坏处:占用多一半内存空间

标记回收法
在这里插入图片描述
优点:不需要额外的空间!
缺点:两次扫描,严重浪费时间,会产生内存碎片

标记整理法
在这里插入图片描述

本篇文字大部分内容来自B站【狂神说Java】JVM快速入门篇

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值