JVM体系结构

  • 类加载器(快递员):

    • 只负责加载java文件,编译后的class文件在文件开头有特定的文件表示,将class文件字节码内容从硬盘加载到JVM内存中并将这些内容转换成方法区的运行时数据结构,至于是否可以正常运行由Execution Engine决定。加载class后为模板Class,该模板存放类的结构信息,一个模板可以实例化多个实例
  • 3个classLoader:启动加载器Bootstrap(C++),扩展加载器Extension(Java),应用程序类加载器AppClassLoader, 分别是祖父孙, 他们都是抽象类,需要被继承。还有用户自定义加载器Java.lang.ClassLoader的子类,用户可以定制类的加载方式, 通过继承ClassLoader类

    • new Object().getClass().getClassLoader()为Bootstrap,是Java祖宗级,在java里输出为null
    • new MyObject().getClass().getClassLoader(),即自己new的类,它的加载器是AppClassLoader , 父加载器为Extension
    • classLoader双亲委派机制:当收到某个java文件的类加载请求,即所有请求都会传送到启动加载类,首先从根加载器(Bootstrap)开始向下寻找,找不到抛ClassNotFound异常,保证了沙箱安全
    • 沙箱安全机制:由双亲委派机制实现,只加载从Bootstrap向下找到的第一个文件,保证Java的源码不被污染,
    • 程序编译时,加载顺序:静态代码块(只加载一次)>构造块>构造方法
  • 本地方法接口:

    • Thread线程类中由native修饰的方法,代表这个方法调用的是底层操作系统和第三方C语言函数库方法, 该方法存放在本地方法栈,其他普通方法存放在java栈。new Thread().start() 只是新建完成到就绪状态,是否被运行决定于底层操作系统和CPU的调度
  • 方法区:java8开始叫元空间

    • 所有线程共享,存在GC,只是量很少,大部分GC在堆里
    • 供各线程共享的运行时内存区域,用于存放每一个类的结构信息,例如运行时常量池、字段和方法数据、构造方法和普通方法的字节码内容、模板Class、static变量。方法区是规范,不同虚拟机实现不同,例如永久代PermGen space 和 元空间 Metaspace
    • java7之前:方法区 f = new 永久代 java8之后:方法区 f = new 元空间
  • 类的实例方法和实例对象存在堆内存中,和方法区无关

  • PC寄存器(程序计数器)

    • 也叫程序计数器,就是一个指针,存放下一条指令的地址,指向下一条要执行的命令,记录了方法之间的调用和执行情况
    • 每个线程都有一个程序计数器,和栈一样都是线程私有的,内存很小几乎不存在GC,不会发生内存溢出
  • 如果执行的是Native方法,那这个计数器为空

  • 栈stack(Java栈):

    • 栈管运行,堆管存储。在Java中,程序 = 框架 + 业务逻辑

    • 线程私有,不存在GC问题,8中基本类型变量+对象的引用变量+实例方法都是在函数的栈内存中分配

    • Java方法被压到栈中,叫做栈帧, main方法最先被压栈,栈帧是内存区,是有关方法和运行期数据的数据集

    • 栈帧中主要保存三类数据:(栈中的数据都是以栈帧的格式存在,在JVM栈里方法叫栈帧,在JVM外叫方法)

      • 本地变量:输入参数和输出参数以及方法内的变量
      • 栈操作:记录出栈、入栈的操作
      • 栈帧数据:包括类文件、方法等
    • 栈运行原理:

    • 栈溢出错误SOF:StackOverflowError

    • A a = new A(); 等号左边是引用,在栈里,等号右边是实例对象,在堆里;

    • 栈、堆和方法区的交互关系:

      • HotSpot(JVM名)使用指针的方式来访问对象,Java堆会存放访问类元数据(Class模板)的地址,reference存储对象的地址
  • 堆(heap)(Java7之前):逻辑上分为以下三部分:

    • 1.新生代(PSYoungGen):
      • 1.伊甸区(Eden Space): new对象存在该区,GC(也叫 YGC 或轻GC 或 MinorGC)在该区产生;在内存超过阈值时开启GC之后,除了正被引用的对象和静态变量被移动到S0区,未存活的对象 被 JVM清除

        • 普通MinorGC:复制(GC复制算法复制到To区) → 清空(Eden和from全部清空) → 互换(S0和S1互换,谁空谁是to区)

          • 复制:第一次GC将Eden区存活的对象复制到S0区后清空Eden区,再次GC后会扫描Eden和S0区进行GC,回收存活的对象并复制到to区(如果有对象的年龄到达老年区的标准则复制到老年区),同时把这些对象年龄+1,以后每次都需要扫描Eden区和S0和S1区,进行MinorGC过程
          • 清空:清空Eden和from区的对象,也即复制之后有交换,谁空谁是to区
          • 交换:To区和From区互换,部分MinorGC存活到15时(由MaxTenuringThreshold决定默认15)后, 存入老年代
      • 2.幸存者0区(Survivor 0 Space, 也叫S0 或 from区):每次GC也会进行复制清空互换的过程
      • 3.幸存者1区(Survivor 1 Space,也叫S1 或 to区):与S0区机制相同
    • 2.老年代(养老区ParOldGen):当对象超过内存阈值后,开启Full GC(也叫FGC或重GC或全局GCMajorGC),多次FGC后无法再腾出空间,将抛出OOM(OutOfMemoryError)堆内存溢出错误,Major GC比 Minor GC慢上十倍左右,每次Major GC经常(不是绝对)伴随一次Minor GC
    • 3.元空间Metaspace(Java7叫永久代或持久代):
      • 用于存放JDK自身携带的Class,Interface的元数据(结构信息),也就是运行环境必须的类信息。被装载进此区域的数据不会被GC,关闭JVM才会释放此区域所占用的内存
      • 对应方法区,虽然逻辑上JVM规范将方法区描述为堆的一个逻辑部分,但物理上不包含在堆里。元空间是方法区的一个实现,即方法区是接口,元空间是实现。
      • 永久代和元空间最大区别:永久代使用JVM的堆内存,而Java8之后的元空间存在于本机物理内存,字符串常量池也在元空间

堆内存调优

  • 元空间存在于本机物理内存,只受本地内存限制,字符串常量池也在元空间,减少了OOM,默认最大JVM Heap堆内存-Xmx只用物理内存的1/4, 最小堆内存-Xms为物理内存的1/64
  • Runtime.getRuntime().totalMemory; // 获取最大堆内存, Runtime.getRuntime()为Runtime Data Area对象
  • JVM调参:
      1. -Xms应该等于-Xmx,避免GC和应用程序争抢内存而导致JVM理论值忽高忽低的问题

GC算法(分代收集算法):只需知道是什么?怎么用?各自的优缺点

  • 1.引用计数法(了解即可):每次GC一个对象被引用就+1,没被引用-1,当为0时就清除。System.gc 不会立刻开启GC

  • 2.复制算法(Copying):年轻代中使用的Minor GC采用的主要是复制算法

    • 是什么:Minor GC的复制过程用到的算法,复制时内存分为两块,一块移动到to区,另一块被清除
    • 优缺点:优点是效率高,不会产生内存碎片, 缺点是耗费空间
  • 3.标记清除:老年代一般是由标记清除或者标记清除与标记整理的混合实现

    • 是什么:先扫描并标记要回收的对象,接着再扫描一次,然后统一回收这些标记的对象

    • 优缺点:优点是不需要额外空间,缺点是两次扫描耗时严重,会产生内存碎片

  • 4.标记压缩(标记整理):

    • 是什么:相当于标记清除,加上移动对象使内存碎片清除

      • 优缺点:优点:标记清除的优点+无内存碎片 缺点:耗时最长
  • 标记清除压缩:标记清除和标记压缩的结合,不同的是:进行多次GC后才压缩,不算入四大算法

  • 没有最好的算法,只有根据每一代GC的特性来采用对应的算法,因此叫分代收集算法


JMM(Java内存模型):可见性、原子性、有序性

JVM是一种抽象概念,描述一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段 、静态字段和守城数组对象的元素)的访问方式

  • volatile是jVM提供的轻量级同步机制

  • 1.可见性:就是个通知机制,一个线程对共享变量的修改,能及时的被其他线程看到

  • 2.原子性:操作不可拆分,要么全成功,要么就不做

  • 3.有序性:如果在本线程内观察,所有操作都是有序的

  • JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(也叫栈空间),工作内存是每个线程的私有数据区域

  • JMM规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作必须在工作内存中进行,首先要将变量从主内存拷贝到自己的工作内存空间,再对变量进行操作,完成后再将变量写回主内存 。不能直接操作主内存中的变量,各个线程中的工作内存中存储着主内存中的变量副本拷贝,因此不同线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成


JUC:java.util.concurrent (Java并发编程工具类)

  • 一般面试提问:面向对象和高级语法、Java集合类、Java多线程、JUC 和高并发、Java IO和 NIO

  • 获取多线程的4种方法:

    1.继承Thread类,重写run方法(其实Thread类本身也实现了Runnable接口)

    2.实现Runnable接口,重写run方法

    3.实现Callable接口,重写call方法(有返回值)

    4.使用线程池(有返回值):通过Executors提供四种线程池

  • 进程:

    • 笔试:具有一定独立功能的程序关于某个数据集合的一次运行活动,是操作系统动态执行的基本单位。
    • 面试:后台运行的一个程序,进程跟操作系统有关,跟编程语言无关,
  • 线程:

    • 笔试:一般一个进程包含多个线程,线程可以利用进程所拥有的资源,在引入线程的操作系统中,把线程作为独立运行和独立调度的基本单位

    • 面试:线程是进程的组成部分,一般一个进程包含多个线程,它代表了一条顺序的执行流。

  • 并发:在同一实体上的两个或多个使事件在同一时间段内发生

  • 并行:在不同实体上的两个或多个事件在同一时刻发生

  • 高内聚:类与类、对象与对象、模块与模块之间高度地聚集和关联

  • 低耦合:AB两个对象可以进行数据共享,但是AB两个对象又各自 独立

  • 在高内聚低耦合的前提下,线程(thread.start())操作(对外暴露的调用方法)资源类(操作的对象):

  • Thread.currentThread().getName() 获取当前线程名

  • Thread(Runnable target, String name) // target:Runnable接口的run() 方法的实现, name:线程名

尚硅谷阳哥JVM笔记的更多相关文章

  1. 尚硅谷STRUTS2视频学习笔记

    上一个月一直在学习STRUTS2,学习的是尚硅谷佟刚老师的视频,因为很喜欢佟刚老师的声音,而且他讲的很细,笔记做的也多,基本上是照着他的视频完整的敲了一遍代码,下面就把学习到的知识梳理一遍,最后把项目 ...

  2. 尚硅谷MySQL高级学习笔记

    目录 数据库MySQL学习笔记高级篇 写在前面 1. mysql的架构介绍 mysql简介 mysqlLinux版的安装 mysql配置文件 mysql逻辑架构介绍 mysql存储引擎 2. 索引优化 ...

  3. 尚硅谷MySQL基础学习笔记

    目录 写在前面 MySQL引入 数据库的好处 数据库的相关概念 数据库存储数据的特点 MySQL服务的启动和停止 MySQL服务端的登录和退出 MySQL的常用命令 MySQL语法规范 DQL(Dat ...

  4. 尚硅谷Oracle教程-学习笔记2

    控制用户权限 1.创建用户 1) SQL> create user atguigu01 2 identified by atguigu01; User created 2) SQL> gr ...

  5. 尚硅谷Java基础学习笔记

    综述: Java学习图谱: 常见dos命令: 操作案例: Java语言的特点: 面向对象 两个基本概念:类.对象 三个基本特性:封装.继承.多态 健壮性.可继承性 write once,run any ...

  6. Spring学习笔记 1. 尚硅谷_佟刚_Spring_HelloWorld

    1,准备工作 (1)安装spring插件 搜索https://spring.io/tools/sts/all就可以下载最新的版本 下载之后不用解压,使用Eclipse进行安装.在菜单栏最右面的Help ...

  7. 尚硅谷spring_boot课堂笔记

    尚硅谷spring_boot课堂笔记

  8. 尚硅谷韩顺平Linux教程学习笔记

    目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...

  9. 保姆级尚硅谷SpringCloud学习笔记(更新中)

    目录 前言 正文内容 001_课程说明 002_零基础微服务架构理论入门 微服务优缺点[^1] SpringCloud与微服务的关系 SpringCloud技术栈 003_第二季Boot和Cloud版 ...

随机推荐

  1. VMware Workstation 15 Pro安装带图形化界面的CentOS7

    1.双击打开“VMware Workstation”,然后选择“创建新的虚拟机” 2.在安装向导中,选择“稍后安装操作系统”,然后点击“下一步”继续安装 3.在“客户机操作系统”中选择“Linux(L ...

  2. C# WebAPI项目,不支持HttpPut请求!!!

    有点标题党了,这个异常的现象是这样的: 我有一个正在跑的项目,要对接第三方厂家的设备.  对方给的接口文档,里面有一个接口是需要我这边实现的,要求必须是PUT请求方式. 所以我在项目基础上,新增一个W ...

  3. 数据结构与算法笔记(java)目录

    数据结构: 一个动态可视化数据结构的网站 线性结构 数组 动态数组 链表 单向链表 双向链表 单向循环链表 双向循环链表 栈 栈 队列 队列 双端队列 哈希表 树形结构 二叉树 二叉树 二叉搜索树 A ...

  4. Jmeter(二十二) - 从入门到精通 - JMeter断言 - 下篇(详解教程)

    1.简介 断言组件用来对服务器的响应数据做验证,常用的断言是响应断言,其支持正则表达式.虽然我们的通过响应断言能够完成绝大多数的结果验证工作,但是JMeter还是为我们提供了适合多个场景的断言元件,辅 ...

  5. springmvc中get和post区别和应用

    最近对post和get什么时候使用 和 应该怎么使用  他俩的区别  有了一些疑问 根据本人的了解   post是对数据进行了封装保护 get是安全性较差的 可以看到数据的信息    post是用来改 ...

  6. 利用JavaScript当鼠标点击导航时改变背景

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 多元线性回归检验t检验(P值),F检验,R方等参数的含义

    做线性回归的时候,检验回归方程和各变量对因变量的解释参数很容易搞混乱,下面对这些参数进行一下说明: 1.t检验:t检验是对单个变量系数的显著性检验   一般看p值:    如果p值小于0.05表示该自 ...

  8. HTML5实战与剖析之媒体元素

    随着HTML5的到来,flash在手机端全部不能得到支持,这就使一项以flash制作的音乐播放和视频播放只能用HTML5中的媒体标签video标签和audio标签来制作了.很恰巧的是,移动端对HTML ...

  9. 方差分析、T检验、卡方分析如何区分?

    差异研究的目的在于比较两组数据或多组数据之间的差异,通常包括以下几类分析方法,分别是方差分析.T检验和卡方检验. 三个方法的区别 其实核心的区别在于:数据类型不一样.如果是定类和定类,此时应该使用卡方 ...

  10. zero:如何找到SEO流量的突破口

    http://www.wocaoseo.com/thread-326-1-1.html 之前一篇文章已有提到过,SEO可以分为两个阶段: 一个阶段是了解点SEO知识,然后就到网站上去找页面,看哪些招式 ...