JVM字节码指令集,寄存器,栈(方法栈和本地方法栈),垃圾回收详解

本文详细介绍了JVM的相关知识,包括字节码指令集、内存分配策略如栈与堆、TLAB(Thread Local Allocation Buffer)的作用,以及垃圾回收机制。讲解了JVM内存结构,如方法区、堆和栈,以及Hotspot虚拟机的后台系统线程。同时,还探讨了Java线程同步与交互的方法,如同步、锁和信号量等,并提到了直接内存的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JVM

包括字节码指令集,寄存器,栈(方法栈和本地方法栈),垃圾回收,堆,方法区,运行在操作系统上,与硬件无交互

这里给大家整理了一些面试题有需要完整版的朋友可以点一点领取:点这里即可领取下面资料!!!,获取码:优快云在这里插入图片描述

新建出来的对象一定会分配在堆上吗

还有可能分配在栈上或者是 和TLAB(Thread Local Allocation Buffer)。
棧:利用逃逸分析来确定是否要分配在堆上,逃逸分析,是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。在计算机语言编译器优化原理中,逃逸分析是指分析指针动态范围的方法,它同编译器优化原理的指针分析和外形分析相关联。当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。沒有逃逸就分配在棧上

TLAB:JVM在内存新生代Eden Space中开辟了一小块线程私有的区域,称作TLAB(Thread-local allocation buffer)。默认设定为占用Eden Space的1%。在Java程序中很多对象都是小对象且用过即丢,它们不存在线程共享也适合被快速GC,所以对于小对象通常JVM会优先分配在TLAB上,并且TLAB上的分配由于是线程私有所以没有锁开销。因此在实践中分配多个小对象的效率通常比分配一个大对象的效率要高。也就是说,Java中每个线程都会有自己的缓冲区称作TLAB(Thread-local allocation buffer),每个TLAB都只有一个线程可以操作,TLAB结合bump-the-pointer技术可以实现快速的对象分配,而不需要任何的锁进行同步,也就是说,在对象分配的时候不用锁住整个堆,而只需要在自己的缓冲区分配即可。

jvm分配内存的流程

编译器通过逃逸分析,确定对象是在栈上分配还是在堆上分配。如果是在堆上分配,则进入选项2.
如果tlab_top + size <= tlab_end,则在在TLAB上直接分配对象并增加tlab_top 的值,如果现有的TLAB不足以存放当前对象则3.
重新申请一个TLAB,并再次尝试存放当前对象。如果放不下,则4.
在Eden区加锁(这个区是多线程共享的),如果eden_top + size <= eden_end则将对象存放在Eden区,增加eden_top 的值,如果Eden区不足以存放,则5.
执行一次Young GC(minor collection)。
经过Young GC之后,如果Eden区任然不足以存放当前对象,则直接分配到老年代。

hotspot后台运行的系统线程包括

虚拟机线程:等待jvm到达安全点操作出现。这些操作有:stop the world,线程栈dump。线程暂停,线程偏向锁解除
周期性任务线程:定时器时间(中断)

gc线程

编译器线程:运行时将字节码动态的编译成本地平台的机器码
信号分发线程:接受发送到jvm的信号并调用适当的jvm方法来处理

基础引入

java语言编写程序(通过编译器javac) class文件(通过jvm解释器)解析为机器指令执行,一次编译到处运行。
编译器:
词法分析器(token流其实就是一种标记)
语法分析器(语法树)
语义分析器(注解抽象语法树)javac
字节码生成器(结构信息,元数据,方法信息)

字节码文件结构:
0-1字符串无分隔符
魔数与Class文件版本
常量池
访问标志
类索引、父类索引、接口索引
字段表集合
方法表集合
属性表集合

字节码指令:
操作码+操作数,操作码总数不超过256条。
java指令集合:加载存储指令,运算指令,类型转化指令,对象创建指令,方法调用指令,异常处理指令,同步指令。

堆栈

1、堆:FIFO队列优先,先进先出。jvm只有一个堆区被所有线程所共享!堆存放在二级缓存中,调用对象的速度相对慢一些,生命周期由虚拟机的垃圾回收机制定。堆的优点-可以动态的分配内存大小,生命周期不确定。缺点-速度略慢
2、栈:FILO先进后出,暂存数据的地方。每个线程都包含一个栈区!栈存放在一级缓存中,存取速度较快,“栈是限定仅在表头进行插入和删除操作的线性表”。栈的优点-速度快,缺点-存在栈中的数据大小和生命周期必须是明确的,缺少灵活性。

jvm中的工具

内存映像分析工具jconsole,jconsole可以显示线程的状态,总数,堆栈,jconsole还有个强大的功能,检测死锁。
jmap, 命令jmap是一个多功能的命令。它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。

线程同步与交互

同步:synchronization和lock
交互:wait notify
semaphore: Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。就这一点而言,单纯的synchronized 关键字是实现不了的。是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。内部是基于AQS的共享模式。它相当于给线程规定一个量从而控制允许活动的线程数。对于Semaphore类而言,就如同一个看门人,限制了可活动的线程数。而对于每辆车来说就如同一个线程,线程需要通过acquire()方法获取许可,而release()释放许可。如果许可数达到最大活动数,那么调用acquire()之后,便进入等待队列,等待已获得许可的线程释放许可,从而使得多线程能够合理的运行。

countdownLatch: 对于倒计数器 ,计数数量为10,这表示需要有10个线程来完成任务,等待在CountDownLatch上的线程才能继续执行。latch.countDown();方法作用是通知CountDownLatch有一个线程已经准备完毕,倒计数器可以减一了。latch.await()方法要求主线程等待所有10个检查任务全部准备好才一起并行执行。 CountDownLatch是java.util.concurrent包中一个类,

直接内存

不是jvm运行时数据区的部分,在NIO中提供了channel和buffer的io方式,可以使用native函数直接分配堆外内存,使用dirextbytebuffer对象做为这块内存的引用,避免在java堆和native堆中复制数据在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值