JVM知识总结

JVM架构图

在这里插入图片描述
垃圾都在heap堆上产生,对象实例和数组都是在堆上分配的,GC主要是针对这两类数据进行回收。JVM调优也是针对堆调优的。

类的加载、连接、初始化

加载:查找并加载类的二进制数据
连接

  • 验证:保证被加载的类的正确性;
  • 准备:给类静态变量分配内存空间,赋值一个默认的初始值;
  • 解析:把类中的符号引用转换为直接引用。

在把java编译为class文件时,虚拟机并不知道所引用的地址;助记符,符号引用,转为真正的直接引用。

  • 初始化:把正确的值赋给类的静态变量。
public class Test{
    public static int a = 1;
}
// 1、加载   编译文件为 .class 文件,通过类加载,加载到JVM
// 2、连接   
	  //验证(1)  保证Class类文件没有问题
      //准备(2)  给int类型分配内存空间,a = 0;
      //解析(3)  符号引用转换为直接引用
// 3、初始化
      //经过这个阶段的解析,把1 赋值给 变量 a;

类的加载

package com.example.springboot.test.jvm;

public class test01 {
    public static void main(String[] args) {
        System.out.println(child.str);
    }
}
class parent {
    static String pStr = "parent str";
    public parent () {
        System.out.println("parent构造方法");
    }
    static {
        System.out.println("parent static");
    }
}
class child extends parent {
    static String str = "child str";
    static {
        System.out.println("child static");
    }
}

打印结果:

parent static
child static
child str

final常量
package com.example.springboot.test.jvm;

public class finalTest {
    public static void main(String[] args) {
        System.out.println(test02.str);
    }
}
class test02 {
    final static String str = "test str";
    static {
        System.out.println("test static");
    }
}

打印结果:

test str

**分析:**final 常量在编译阶段的时候放入常量池,代码中把str常量放入了finalTest的常量池中,之后和finalTest和test02就没有关系了。如果str不是final,则会打印出test static。
如果把代码换成下面的

package com.example.springboot.test.jvm;

import java.util.Random;

public class finalTest {
    public static void main(String[] args) {
        System.out.println(test02.str);
    }
}
class test02 {
    final static String str = String.valueOf(new Random(10).nextInt());
    static {
        System.out.println("test static");
    }
}

则输出结果为:

test static
-1157793070

分析: 当一个常量的值并非编译期间可以确定的,那这个值就不会被方法调用类的常量池中!程序运行期间的时候,会主动使用常用所在的类。

ClassLoader 分类

1、java虚拟机自带的加载器

  • BootStrap 根加载器 (加载系统的包,JDK 核心库中的类 rt.jar)
  • Ext 扩展类加载器 (加载一些扩展jar包中的类)
  • Sys/App 系统(应用类)加载器 (我们自己编写的类)

2、用户自己定义的加载器

  • ClassLoader,只需要继承这个抽象类即可,自定义自己的类加载器
双亲委派机制

双亲委派机制 可以保护java的核心类不会被自己定义的类所替代,
一层一层的让父类去加载,如果顶层的加载器不能加载,然后再向下类推。

native方法

只要是带了native这个关键字的,说明 java的作用范围达不到,只能去调用底层 C 语言的库!

程序计数器

每个线程都有一个程序计数器,是线程私有的。
程序计数器就是一块十分小的内存空间;几乎可以不计。
作用: 看做当前字节码执行的行号指示器。
分支、循环、跳转、异常处理!都需要依赖于程序计数器来完成!

方法区

方法区(Method Area )是 Java虚拟机规范中定义的运行是数据区域之一,和堆(heap)一样可以在线程之间共享!
JDK1.7之前

永久代:用于存储一些虚拟机加载类信息,常量,字符串、静态变量等等。。。。这些东西都会放到永久代中;
永久代大小空间是有限的:如果满了 OutOfMemoryError:PermGen
JDK1.8之后

彻底将永久代移除 HotSpot jvm ,取而代之的是元空间;
元空间就是方法区在HotSpot jvm中的实现;
方法区重要就是来存:类信息,常量,字符串、静态变量、符号引用、方法代码。
元空间和永久代,都是对JVM规范中方法区的实现。
元空间和永久代最大的区别:元空间并不在Java虚拟机中,使用的是本地内存!

栈stack

什么是栈?
栈是管理程序运行的,存储一些基本类型的值、对象的引用、方法等。
在这里插入图片描述
栈的优势:存取速度比堆快!仅次于寄存器,栈的数据是不可以共享的;
栈里面是一定不会存在垃圾回收的问题的,只要线程一旦结束,该栈就结束了。生命周期和线程一致;

stack原理

java栈的组成元素:栈帧。
在这里插入图片描述
栈、堆、方法区的交互关系图:
在这里插入图片描述
栈中的对象引用引用堆中的具体的实例化对象,堆的实例化对象模板在方法区内。

三种JVM

  • SUN 公司 HotSpot
  • BEA 公司 JRockit
  • IBM 公司 J9VM

堆heap

Java7之前:

Heap 堆,一个JVM实例中只存在一个堆,堆的内存大小是可以调节的。
可以存的内容:类、方法、常量、保存了类型引用的真实信息
分为三个部分:

  • 新生区:Young (Eden-s0-s1)(伊甸园区、幸存0区、幸存1区)
  • 养老区:Old Tenure
  • 永久区:Perm

堆内存在逻辑上分为三个部分:新生、养老、永久(JDK1.8以后,叫元空间)
物理上只有 新生、养老;元空间在本地内存中,不在JVM中!
GC 垃圾回收主要是在 新生区和养老区,又分为 普通的GC 和 Full GC,如果堆满了,就会爆出 OutOfMemory;

新生区

新生区 就是一个类诞生、成长、消亡的地方!

新生区细分: Eden、s(from to),所有的类Eden被 new 出来的,慢慢的当 Eden 满了,程序还需要创建对象的时候,就会触发一次轻量级GC;清理完一次垃圾之后,会将活下来的对象,会放入幸存者区(),… 清理了 15次之后,出现了一些极其顽强的对象,有些对象突破了15次的垃圾回收!这时候就会将这个对象送入养老区!运行了几个月之后,养老区满了,就会触发一次 Full GC;假设项目1年后,整个空间彻彻底底的满了,突然有一天系统 OOM,排除OOM问题,或者重启;

Sun HotSpot 虚拟机中,内存管理(分代管理机制:不同的区域使用不同的算法!)

99% 的对象在 Eden 都是临时对象;

养老区

15次都幸存下来的对象进入养老区,养老区满了之后,触发 Full GC

默认是15次,可以修改!但是只能改小,不能超过15。

永久区(Perm)

放一些 JDK 自身携带的 Class、Interface的元数据;
几乎不会被垃圾回收的;

  • JDK1.6之前: 有永久代、常量池在方法区;
  • JDK1.7:有永久代、但是开始尝试去永久代,常量池在堆中;
  • JDK1.8 之后:永久代没有了,取而代之的是元空间;常量池在元空间中;
    方法区和堆一样,是共享的区域,是JVM 规范中的一个逻辑的部分,但是记住它的别名 非堆
    元空间:本地内存!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值