直接内存
从JDK8开始,出现了元空间,把方法区直接移到了直接内存中,
回顾IO和NIO
IO是阻塞式的,NIO(Non-blocking IO)非阻塞式
IO是通过字节数组byte[]和字符数组char[]实现的stream流
而NIO是通过Buffer实现的,使用Channel通道
如果要操作直接内存,使用NIO的方式
通过ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);来分配固定大小的直接内存
使用IO的方式
使用NIO的方式
如果读写操作频繁或者是大文件,那么使用NIO的直接内存效率更高,速度提升明显
如果发生OOM。还需要考虑是不是本地内存不够的问题
整个的一个java进程的内存可以理解为java堆内存加上本地内存
整个虚拟机的构成要会画出来
执行引擎
执行引擎完成的工作就是把字节码指令翻译成机器指令
执行引擎工作过程:其实就是把字节码文件中的字节码指令依次翻译成机器指令然后去执行,最后返回结果
解释器和JIT
为什么说java是半编译半解释型语言?
因为java代码执行的时候,在执行引擎中既存在解释器,也存在JIT及时编译器的处理
机器码、指令、汇编语言
机器码,对应的就是机器语言
汇编语言
高级语言
记住:
C的执行过程
java字节码
生成字节码文件的目的其实就是为了保证语言的跨平台性,保证class文件在不同平台都能运行,而不管操作系统是什么类型
解释器
JIT编译器
JIT比解释器执行速度快,因为已经翻译成了机器指令
解释器的优势就是响应速度快,
JIT需要先翻译成本地代码,然后速度才会比解释器快
解释器和JIT编译器共存的原因
JRocket之所以速度快,是因为只有JIT编译器,使用的场景是服务器端,在服务器端更多考虑的是程序的性能
而不关注程序启动的时间,等待JIT把代码编译成本地代码后,那么执行效率就很高了
而Java的应用场景是有客户端的,客户端就要考虑到一个响应时间,不能让客户去等待JIT的编译,所以要在编译器和JIT之间找一个平衡,
保证客户端同样有高效的响应。
解释器
热点代码
方法调用计数器
要经过JIT编译器编译的代码,必须达到计数器设定的阈值,这个阈值可以自己设置,当超过阈值后就会触发即时编译
但是计数器不会一直增加,而是有一个热度衰减,统计的是一段时间中这段代码的执行次数。一段时间未执行那么就会把计数器减少一半
Hotspot可以设置只使用解释器或者只使用JIT的模式,或者两种方式混合