谈谈JVM的理解
JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序
一个JVM只有一个堆内存,并是可以调整大小的
说说几种主要的JVM参数
堆栈配置相关
-Xmx3550m: 最大堆大小为3550m。
-Xms3550m: 设置初始堆大小为3550m。
-Xmn2g: 设置年轻代大小为2g。
-Xss128k: 每个线程的堆栈大小为128k。
-XX:MaxPermSize: 设置持久代大小为16m
-XX:NewRatio=4: 设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。
-XX:SurvivorRatio=4: 设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
-XX:MaxTenuringThreshold=0: 设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。
垃圾收集器相关
-XX:+UseParallelGC: 选择垃圾收集器为并行收集器。
-XX:ParallelGCThreads=20: 配置并行收集器的线程数
-XX:+UseConcMarkSweepGC: 设置年老代为并发收集。
-XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。
-XX:+UseCMSCompactAtFullCollection: 打开对年老代的压缩。可能会影响性能,但是可以消除碎片
什么是oom 什么是栈溢出,
oom 堆内存不够
1.扩大内存在运行看结果是否ok
2.分析内存,使用专业工具
MAT或Jprofiler工具: 能够看到哪一行代码出错
JVM的常用调优参数有哪些
-Xms :设置初始化内存分配大小 默认是本机内存的1/64
-Xmx:设置最大分配内存 默认是本机内存的1/4
-XX:+PrintGCDetails //打印GC垃圾回收信息
-XX:+HeapDumpOnOutOfMemoryError //弹出oom异常信息文件
内存快照如何抓取,怎么分析Dump文件
谈谈类加载器ClassLoader
作用:加载Class文件
应用类加载器->扩展类加载器->根加载器
步骤:
1.类加载器收到类加载的请求
2.将这个请求向上级委托给父类加载器加载完成,委托到最上级,直到启动类加载器
3.启动类加载器检查是否可以加载当前类,可以就加载,否则抛出异常,通知子类加载器加载,直到可以加载.最后不能可以加载抛出异常
JVM的位置
运行在操作系统上,例如Window,Linux系统,JRE内部
JVM 体系结构
java源代码,编译后.class的字节码文件->类装载器->JVM中的运行时数据区 (方法区,java栈 ,本地方法栈,堆,程序计数器)->外面的 本地方法接口, 本地方法库, 执行引擎
在栈,本地方法栈, 程序计数器中不会存在GC
JVM调优就是针对 堆
双亲委派机制
是一个安全检测机制,主要防止有人恶意篡改源码,
原理:加载一个类之前,加载器会判断自己是否加载过,没有就向上委派父级加载器加载.直到最高父级加载器,最高父级加载器不能加载抛出异常让子加载器加载, 这个过程中如果有恶意写的类,会被加载器察觉,并抛出异常
沙箱安全机制
沙箱是限制程序运行的环境,为了java运算的安全,限制了运作的环境范围
Native 本地方法栈
凡是代理Native关键字的,声明java的作用范围达不到了,会去调用底层C语言的库,会进入本地方法栈调用本地方法接口 JNI
它在内存区域中专门开辟了一个标记区域: 本地方法栈,登记 native方法,在最终执行的时候,加载
JNI的作用 :扩展java的使用,融合 不同的编辑语言为Java所用
PC寄存器
每个线程都有一个,可以当成是指针,指向方法区中的方法字节码,占用空间非常小
方法区
方法区是线程共享,所有定义的方法的信息都保存在该区域,
静态变量,常量,类信息(构造器,接口定义),运行时的常量池,但实例变量的赋值存在堆内存中
栈 数据结构
程序=数据结构+算法
栈: 先进后出,后进先出
主管程序的运行,生命周期和线程同步,线程结束,栈内存就会释放,对于栈,没有GC
栈中放的就是8大基本类型,对象引用,实例的方法
栈的运行原理: 栈帧,一个方法可以理解为一个栈帧,
堆
堆分为三个区:新生区.老年期,永久区
默认的情况下:分配的总内存是电脑内存的1/4,而初始化内存为1/64
永久区
jdk1.8之后永久区该名字叫元空间 存储java运行时的一些环境或类信息,这个区域不存在垃圾回收,在关闭JVM的时候释放内存
在加载大量的第三方jar包,tomcat部署太多应用,大量动态生成反射类,不断加载就会出现oom
逻辑上存在,物理上不存在(可以算出来)
新生区和老年区
新生区分为:
伊甸园: 所有类都在这诞生
幸存区0区
幸存区1区
在新生区经过GC回收15次还没被回收就会进入老年区,在养老区既老年区还没被回收就会进入永久区
GC垃圾回收机制主要在新生区和老年区
堆内存调优
对堆内存的大小更具实际项目需求情况设置, 例如 初始化大小, 标记压缩算法中多少次标记后进行压缩
GC
分为两种类型: 轻GC(普通的GC),重GC(全局GC)
GC的算法
标记清除法 扫描给对象加标签,在扫描将没有变标签的对象回收,
缺点:2次扫描浪费时间,会出现内存空间碎片
复制算法: 作用于新生区,每一次GC回收都会讲幸存者to内存清空,将伊甸园区和to区中存活下来的数据复制转移到幸存者from区
好处是没有内存的碎片,
坏处浪费了内存空间,to空间永远为空
引用计数器: 给每个对象分配一个计数器,用于记录当前引用次数为几,当为0的时候,进行回收 , 但计数器本身会有消耗,效率不高,现在基本都不使用了
JMM
什么是JMM
java内存模型 ,是一个概念,一种规则
它干什么的?
作用:缓存一致性协议,用于定义数据读写规则
好处是没有内存的碎片,
坏处浪费了内存空间,to空间永远为空
引用计数器: 给每个对象分配一个计数器,用于记录当前引用次数为几,当为0的时候,进行回收 , 但计数器本身会有消耗,效率不高,现在基本都不使用了
JMM
什么是JMM
java内存模型 ,是一个概念,一种规则
它干什么的?
作用:缓存一致性协议,用于定义数据读写规则
用于解决多线程中线程之间数据的可见性问题 ,使用 Volilate实现