首页 > 其他分享 >JVM

JVM

时间:2022-11-22 11:35:48浏览次数:66  
标签:Java 标记 算法 内存 JVM new 加载

JVM探究

1、JVM的位置

image-20221116091617106

 

2、JVM的体系结构

image-20221116092532131

image-20221116092646056

image-20221116092731157

image-20221116092818732

 

 

3、类加载器

作用:加载Class文件。

new Student();使用new关键字之后就会得到一个具体的实例,它的引用在栈里边,具体的人在堆里边。

image-20221116132449037

Car car1 = new Car();

Car car2 = new Car();

Car car3 = new Car();

栈中存的是car1,car2,car3的名字,真正的值是存放在堆中的,car1(name=“1“,age=1),car2(name=“2“,age=2),car3(name=“3“,age=3),栈中存的名字和堆中存的具体数值是有内存地址引用的。

这三个对象都是一个类加载器模板,但却是三个不同的对象。

  1. 虚拟机自带的加载器

  2. 启动类(根)加载器

  3. 扩展类加载器

  4. 应用程序加载器

image-20221116132737286

 

4、双亲委派机制

为了保证安全。

按照层级查找

  • 类加载器收到类加载的请求 Application

  • 将这个请求向上委托给父类的加载器去完成,一直向上委托,直到启动类加载器

  • 启动加载器检查是都能够加载当前这个类,能加载就结束,使用当前的加载器,否则抛出异常,通知子加载器加载

  • 重复步骤3(启动加载器检查是都能够加载当前这个类,能加载就结束,使用当前的加载器,否则抛出异常,通知子加载器加载)

跟加载器(jre根目录中的rt.jar)>扩展加载器(jre目录中lib目录中)>自定义加载器(应用程序中)

 

  1. APP-->EXC-->BOOT(最终执行)

  2. 如果BOOT中没有会去EXC中找

  3. 如果EXC中没有会去APP中找

image-20221116133424262

 

5、沙箱安全机制

image-20221116134728818

image-20221116134817139

image-20221116134904825

image-20221116134931435

image-20221116135532031

image-20221116135637167

6、Native

public class Demo {

   public static void main(String[] args) {
       new Thread(()->{

      },"测试线程名称").start();
  }

   //凡是带了native关键字的,说明Java的作用范围达不到了,去调用底层C语言的库
   //会进入本地方法栈
   //调用本地方法本地接口,JNI:Java native Interface
   //JNI作用:扩展Java的使用,融合不同 的编程语言为Java所用
   //Java诞生的时候C、C++横行,要想立足,必须要有调用C、C++的程序
   //它在内存区域中专门开辟了一块标记区域:Native Method Stack,登记Native方法
   //在最终执行的时候,加载本地方法库中的方法通过JNI
   private native void hello();
}

image-20221116141508419

7、PC寄存器

image-20221116141533102

8、方法区

image-20221116141555579

static,final,Class,常量池

image-20221116141858315

image-20221116141945467

image-20221116142813303

9、栈

数据结构

栈:先进后出、后进先出:桶

队列:先进先出(FIFO:First Input First Output)

喝多了吐就是栈,吃多了拉就是队列

为什么main方法先执行,最后结束

image-20221116143813630

栈溢出

image-20221116143902869

栈:栈内存,主管程序的运行,生命周期和线程同步;

线程结束,栈内存也就释放,对于栈类说,不存在垃圾回收问题

一旦线程结束,栈就Over!

栈中存储的东西:8大基本类型+对象的引用+实例的方法

栈运行原理:栈帧

栈买了就会抛出错误:StackOverFlowError

image-20221116144621046

栈+堆+方法区:交互关系

image-20221116145118767

10、三种JVm

  • Sun公司 HotSpot

    image-20221116145432477

     

  • BEA Oracle JRockit

  • IBM J9 VM

11、堆

Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。

类加载器读取了类文件后,一般会把类实例,方法,常量,变量放入堆中。保存所有引用类型的真实对象。

堆内存中还要细分为三个区域:

  • 新生区(伊甸园区)Young/New

  • 养老区 Old

  • 永久区 Perm

image-20221116150807255

GC垃圾回收,主要是在伊甸园区和养老区。

假设内存满了,就会报错,OOM,堆内存不够。java.lang.OutOfMemoryError:Java heap space

在JDK8以后,永久存储区改了个名字(元空间);

image-20221116151242912

  • 新生区

    • 类:诞生和成长的地方甚至死亡;

    • 伊甸园,多有的对象都是在伊甸园区new出来的。

    • 幸存区(0,1)

  • 老年区

     

image-20221116152730247

真理:经过研究,99%的对象都是临时对象!

  • 永久区

    这个区域常驻内存的。用来存放JDK自身携带的Class对象,Interface元数据,存储的是Java运行时的环境或类信息,这个区域不存在垃圾回收。关闭虚拟机就会释放这个区域的内存。

    一个启动类,加载了大量的第三方jar包;tomcat部署了太多的作用;大量动态生成的反射类,不断的被加载,知道内存满,就会出现OOM

    • jdk1.6之前:永久代,常量池是在方法区

    • jdk1.7 :永久代,慢慢的退化了,去永久代,常量池在堆中

    • jdk1.8之后:无永久代,常量池在元空间

image-20221116153845001

元空间:逻辑上存在,物理上不存在

public class Test {

   public static void main(String[] args) {
       //获取试图使用的最大内存
       long maxMemory = Runtime.getRuntime().maxMemory();
       //获取初始化的总内存
       long totalMemory = Runtime.getRuntime().totalMemory();

       System.out.println("最大内存:"+maxMemory+"字节\t"+maxMemory/(double)(1024*1024)+"M");
       System.out.println("总内存:"+totalMemory+"字节\t"+totalMemory/(double)(1024*1024)+"M");
  }
   /***
    -Xms1024m -Xmx1024m -XX:+PrintGCDetails
    -Xms为总内存
    -Xmx为最大内存
    遇到OOM:
       1、尝试扩大堆内存看结果
       2、分析内存,看一下哪个地方出现了问题(工具)
    */


}

image-20221116155758960

image-20221116155954516

image-20221116160231630

项目突然出现OOM故障,应该如何排错:

  • 能够看到代码第几行出错:内存快照分析工具,(eclipse插件)MAT,Jprofiler

  • Debug,一行一行的分析

MAT,Jprofiler作用:

  • 分析Dump内存文件,快速定位内存泄露

  • 获得堆中的数据

  • 获得大的对象

  • .....

Jprofiler官网https://jprofiler.en.softonic.com/

Idea中下载Jprofiler插件

12、GC

image-20221118100541118

image-20221118100600452

GC分为两种:

轻GC:在Eden区

重GC(Full GC):在养老区

  • 引用计数法

image-20221118100620012

 

  • 复制算法

image-20221118090438411

 

image-20221118091350653

好处:没有内存碎片

坏处:浪费内存空间,有一半幸存区永远是空的to区。

复制算法最佳使用场景:对象存活度较低的时候。

  • 标记清除算法

    image-20221118092017449

    优点:不需要额外的空间,相对复制算法的to区。

    缺点:两次扫描严重浪费时间,会产生内存碎片。

  • 标记清除压缩

    image-20221118092338979

     

    总结

    内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)

    内存整齐度:复制算法=标记压缩算法>标记清除算法

    内存利用率:标记压缩算法=标记清除算法>复制算法

     

     

    13、JMM

 

标签:Java,标记,算法,内存,JVM,new,加载
From: https://www.cnblogs.com/wx-36/p/16914591.html

相关文章

  • 重新认识下JVM级别的本地缓存框架Guava Cache——优秀从何而来
    大家好,又见面了。本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面。如果感兴趣,欢迎关注以获取后续更新。不......
  • jstat查看jvm的GC情况[转]
    jps(JavaVirtualMachineProcessStatusTool)是JDK1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情......
  • JVM笔记4-垃圾回收
    文章目录视频资源地址笔记资源地址我的笔记48-49.判断垃圾-引用计数50.可达分析51.可达分析-根对象视频资源地址B站https://www.bilibili.com/video/av7054......
  • JVM虚拟机(整体架构、类文件结构)我来了~~~
    虚拟机1.1发展历程1.1.1java往事​ Java诞生在一群懒惰、急躁而傲慢的程序天才之中。​ 1990年12月,Sun的工程师PatrickNaughton被当时糟糕的SunC++工具折磨的快疯......
  • JVM知识
    1什么是jvm?https://blog.csdn.net/a111042555/article/details/126284746JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节......
  • JVM加载中初始化时机?什么时候不会进行初始化?
    初始化的过程是给静态变量赋予指定值以及执行静态代码块的过程。当遇到new,getstatic,putstatic,invokestatic指令时要进行初始化,也就是new实例化对象,调用静态变量以及静态方......
  • JVM - 1.内存结构
    1内存结构1.1程序计数器1.1.1作用在执行的过程中,记住下一条jvm指令的执行地址物理上通过寄存器实现1.1.2特性每个线程都有自己的程序计数器-线程私有......
  • JVM指令手册
    一、栈和局部变量操作将常量压入栈的指令aconst_null将null对象引用压入栈iconst_m1将int类型常量-1压入栈iconst_0将int类型常量0压入栈iconst_1将int类型常量1......
  • JVM内存结构与内存模型
    这篇文章重点讲一下jvm的内存结构和内存模型的知识点。1、内存结构jvm内存区域主要分为线程私有区域【程序计数器,虚拟机栈,本地方法栈】,线程共享区域【堆,方法区】,直接内存......
  • 08.大促高并发系统下JVM如何调优指导(4)
                                                         ......