Jvm虚拟机,运行在操作系统之上,编译执行java代码
1, 面试官:手绘一个类加载过程
补充: 这里的执行硬件 java 调用 c++ 指令 创建线程 ,new thread()->start() 底层代码就是
native start0();这个方法(该方法就是c++指令);
面试官: 什么双亲委派机制 ?
小菜: 其实就是父类委派 ,类加载器收到new String()指令 就向上从 root (rt,jar)找 -》 ext(文件下的jar) -》 最后执行,
例如 String 存在 rt.jar 如果自动一个同名,那么就报错,双亲委派,父类里面不被重写,安全性。
方法区:静态变量、常量、 类信息(构造方法,接口定义) ,运行时的常量池也在内,实力变量在堆内存中;(非堆)
栈: 栈内存, 主管程序的运行,生命周期,和线程同步,
即 局部变量、部分结果,并参与方法的调用和返回;
(
- Java虚拟机栈(Java Virtual Machine Stack) ,早期也叫Java栈。
- 每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame) ,对应着一次次的Java方法调用。
- 是线程私有的
)
堆 :
程序运行时动态申请和释放区域,
实例对象和数组;我们常说的jvm 调优就是调节堆内存,
从划分区分,新生区(伊甸园区(幸福区1 幸福区2)),老年区, 永生区(元空间,jdk1.8)永久代就是 JVM 的方法区。在这里都是放着一些被虚拟机加载的类信息,静态变量,常量等数据。这个区中的东西比老年代和新生代更不容易回收。;
面试题:开发中遇到的异常有哪些?
Java虚拟机规范允许Java栈的大小是动态的或者是固定不变的。
如果采用固定大小的Java虚拟机栈,那每一个线程的Java虛拟机栈容量可以在线程创建的时候独立选定。如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出一个StackOverflowError异常。
如果Java,虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,那Java虚拟机将会抛出一个OutofMemloryError 异常。
总结: 栈是运行时的单位,而堆是存储的单位。即:栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。堆解决的是数据存储的问题,即数据怎么放、放在哪儿。
GC:
垃圾回收, 分为 minor GC ,轻量级回收,当eden 区满时候,出发一次,即申请一个对象是发现eden区不够,触发一次轻gc; 触发之后,from -to 存活的的第项会移动到幸福区,无用对象被回收。
Major Gc 和 full GC 触发条件一般为: Major GC (重gc) 通常是跟full GC 是等价的
他的触发时机一般不是固定的,而是根据jvm 根据堆内存的使用情况,对象的存活情况以及gc 算法等因素决定。
1, 一般情况 老年代内存不足,: 当老年代区域的空间不足会触发。
2,程序中system.gc() 可以触发;但是这只是发出通知,实际根据jvm 算法 决定
GC ;垃圾回收算法: 复制算法(轻gc),从一块内存复制到另一块内存;速度快,没有内存碎片,需要消耗内存空间;
标记清除(老年代):将标记的对象,清除, 速度快,不消耗内存空间,但是会造成内存碎片;
标记压缩 : 在标记清除的算法上改良,标记清楚后,进行内存压缩,缺点:扫描两次;
老年代区域就是用标记清除 在压缩;
住:只有经历 15 次 Minor GC 还能在新生代中存活的对象,才会被送到老年代 ,减少老年代的区域过早的满,因为满了 需要触发full Gc 这会非常消耗时间;
jvm 内存分析命令 :
当出现OutOfmemaryError,
jps : 显示系统内所有hotspoot 进程
jmap , 用于生成 heap dump 文件,如果不使用这个命令,还可以使用
-XX:+HeapDumpOnOutOfMemoryError
参数来让虚拟机出现 OOM 的时候自动生成 dump 文件;jmap -heap 进程id 查看堆信息;
jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。
-l :
-l :除了输出堆栈信息外, 显示关于锁的附加信息
jstack -l 线程id|more