jvm 概念整理1

虚拟机 virtual machine

虚拟计算机 ,分为系统虚拟机和程序虚拟机
1. visual Box ,VMare
2. java虚拟机 专门为执行单个计算机程序而设计

  • 三种jvm
    1. Sun公司的HotSpot
    2. BEA公司的JRockit
    3. IBM公司的 J9 VM

学习目的

熟悉JVM架构与GC垃圾回收机制以及相应的堆参调优,有过在linux进行系统调优的经验

调优目的

减少gc full gc

java 虚拟机内存结构

在这里插入图片描述

  1. 拥有独立运行的机制,二进制的运行环境
  2. java 平台上的多语言混合编程
  3. JVM是运行在操作系统之上的,他与硬件没有直接的交互。
  4. java编译器输入的指令流基于栈的指令集架构
    跨平台、指令集小、指令多:执行性能比寄存器差

特点

一次编译 处处运行
自动内存管理
自动垃圾回收

体系结构概览

Class Loader类加载器

负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,值与他是否可以允许,则由Execution Engine决定

Execution Engine 执行引擎 负责解释命令,提交操作系统执行
Native Interface 本地接口

与其他语言交互接口,Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。

Runtime Data Area 运行数据区
  1. 堆 heap
    实例变量存在堆内存
  • 对象包含
    1. 对象头
    2. 实例数据
    3. 对齐填充
  1. Java Stack 栈 ( 栈管运行,堆管存储)(线程私有)
    栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。基本类型的变量、实例方法、引用类型变量都是在函数的栈内存中分配
    栈(线程) 局部变量 一个方法对应一个栈帧内存区域
    • 栈帧
      1. 局部变量表: 对象指针指向堆的对象、输入参数和输出参数以及方法内的变量
      2. 操作数栈: 记录出栈、入栈的操作
      3. 动态链接: 内存位置
      4. 方法出口:返回位置
  2. Native Method Stack 本地方法栈 (线程私有)
    java在内存中专门开辟了一块区域处理标记为native的代码,他的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载native libraies。
  3. Method Area方法区
    方法去是被所有线程共享,所有字段和方法字节码、以及一些特殊方法如构造函数,接口代码也在此定义。简单说,所有定义的方法的信息都保存在该区域此区属于共享区间。用来保存装载的类的元结构信息。
    静态变量+对象指向(堆) +常量+类信息+运行时常量池存放在方法区
  4. PC Register 程序计数器 (线程私有)
    每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个将要执行的指令代码),有执行引擎读取下一条指令,是一个非常小的内存空间,可以忽略不记
垃圾回收
内存区域划分
  1. 新生代 1
    1. eden区 8
    2. survivor 1 1
  2. 老年代 3
  3. 永久代(1.8之前)在jvm内存里
    元空间(1.8之后)在jvm内存外
  • 新生代
    新生区是类的诞生、成长、消亡的区域,一个类再这里产生,应用,最后被垃圾回收器收集,结束生命。新生去又分欸两部分:伊甸区(Eden Space)和幸存者区(Survivor Space),所有的类都是再伊甸区被new出来。幸存区又连个:0区和1区。当伊甸园的空间用完是,程序有需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园区中的生于对象移动到幸存0区,若幸存0区也满了,再对该区进行垃圾回收,然后移动到1区。如果1区也满了,再移动到养老区。若养老区也满了,那么这时候将产生MajorGC(FullGC),进行养老区的内存清理。若养老区执行了FullGC后发现依然无法进行对象保存,就会产生OOM异常(OutOfMemoryError)。
  • 如果出现java.lang.OutOfMemoryError:Java heap space异常,说明java虚拟机的堆内存不够。原因有二:

    1. Java虚拟机的对内存设置不够,可以通过参数-Xms、-Xmx来调整,默认最大内存是机器的四分之一大小
    2. 代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)
  • 老年代
    用于保存从新生区筛选出来的JAVA对象,一般池对象都在这个区域活跃。
  • 永久代
    永久存储区是一个常驻内存区域,用于存放JDK滋生所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。
  • 如果出现java.lang.OutOfMemoryError:PermGen space,说明是Java虚拟机对永久带Perm内存设置不够,一般出现这种情况,都是程序启动需要加载大量的第三方jar包。例如在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载,最终导致Perm区被沾满。
    • Jdk1.6之前:有永久代,常量值1.6在方法区
    • Jdk1.7:有永久代,但已经逐步“去永久代”,常量池1.7在堆
    • Jdk1.8之后:无永久代,常量池1.8在元空间
gc 垃圾收集

JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代。因此GC按照回收的区域又分了两种类型,一种是普通GC(MinorGC),一种时全局GC(FullGC)

  • 普通GC:只针对新生代区域的GC
  • 全局GC:针对年老代的GC,偶尔伴随对新生代的GC以及堆永久代的GC。
    gc触发stw
  • 对象动态年龄判断
  • 长期存活的对象将进入老年代
  • 老年代空间分配担保机制
stw

暂停线程 标记垃圾

判断垃圾算法
  1. GC Roots :可达性分析算法
    可以作为根
    1. 线程栈的本地变量
    2. 静态变量
    3. 本地方法栈的变量
垃圾回收算法
  1. 复制算法
  2. 标记整理
  3. 标记清楚
堆内存调优
-Xms设置初始分配大小,默认为物理内存的“1/64”
-Xmx最大分配内存,默认为物理内存的“1/4”
-XX:+PrintGCDetails输出详细的GC处理日志

小总结

逻辑上堆由新生代、养老代、元空间构成、实际上堆只有新生和;老年代;方法区就是永久代,永久代是方法区的实现

  • 方法区(Method Area)和堆一样,是各个线程共享的内存区域,它用于存储虚拟机加载的类信息、普通常量、静态常量、编译器编译后的代码等,虽然JVM规范将方法去描述为堆的一个逻辑部分,但他却还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。
  • 对于HotSpot虚拟机,很多开发者习惯将方法区成为“永久代”,但严格本质上说两者不同,或者说使用永久代来实现方法区而已,永久代是方法区(相当于一个接口Interface)的一个实现,JDK1.7的版本中,已经将原本放在永久代的字符串常量池移走。
  • 常量池(Constant Pool)是方法区的一部分,Class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量池中存放

java 执行流程

在这里插入图片描述

jvm生命周期

  1. 虚拟机启动
    引导类加载器(bootstrap class loader)创建一个初始类(initial class),这个类由虚拟机具体实现指定
  2. 执行
    真真正正执行一个java进程
  3. 退出
    线程调用runtime类或system类的exit方法,或runtime类的halt方法,
英语

native 本地

命令

jps 打印进程
javap
thread+ 线程
jad +class
javap -v 类

调优工具

arthas
jvisualvm

eg

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值