JVM 01

7 阅读4分钟

使用堆外内存的优点

减少垃圾回收(因为垃圾回收会暂停其他的工作) 加快了复制的速度(堆内的flush到远程时,会复制到直接内存(非堆内存),然后在发送;而堆外内存相当于省略掉了这个工作)

类常量池、运行时常量池、字符串常量池有什么关系?有什么区别?

类常量池与运行时常量池都是存储在方法区,而字符串常量池在JDK7时就已经从方法区迁移到了java堆中

在类编译过程中,会把类元信息放到方法区,类元信息的其中一部分便是类常量池,主要存放字面量和符号引用。而字面量的一部分便是文本字符,在类加载时将字面量和符号引用解析为直接引用存储在运行时常量池。

对于文本字符来说,它们会在解析时查找字符串常量池,查找这个文本字符对应的字符串对象的直接引用,将直接引用存储在运行时常量池,字符串常量池存储的时字符串对象的引用,而不是字符串本身。

说下堆栈的区别?

物理地址区别: 堆:栈的物理地址分配是不连续的,因为性能慢。在GC的时候也要考虑到不连续的分配,所以有各种算法:标记-清除,复制,标记-压缩,分代(新生代使用复制算法,老年代使用标记-压缩) 栈:使用的是数据结构中的栈,先进先出原则,物理地址分配是连续的,性能快

内存区别: 堆因为是不连续的,所以分配的内存是在运行期确定的,因此大小不是固定的 栈是连续的,所以分配的内存在编译期间就确定的,大小是固定的

存放的内容区别: 堆存放的是:对象的实例和数组,因此该区更关注的是数据的存储。 栈存放的是:局部变量、操作数栈、返回结果,该区更关注的是程序方法的执行

程序的可见性区别: 堆对于整个程序都是共享的、可见的 栈只对于线程是可见的,线程私有的,它的生命周期和线程是相同的。

队列和栈是什么,有什么区别?

队列和栈都是用来预存储数据的

  • 操作的名称不同,队列的插入被称为入队,队列的删除被称为出队。栈的插入被称为进栈,栈的删除被称为出栈
  • 操作的方式不同,队列在队尾入队,在队头出队,即:两边都可以操作。栈的进栈和出栈都是在栈顶
  • 操作的方法不同,队列是先进先出(FIFO),栈为后进先出(LIFO)

什么是直接内存?

直接内存并不是JVM运行时数据区的一部分,但也会被频繁的使用。JDK1.4时引入NIO提供了基于Channel和Buffer的IO方式,它可以使用Native函数库直接分配堆外内存,然后使用DirectByteBuffer对象作为这块内存的引用进行操作,这样就避免了在java堆和native堆中的来回复制数据,因此在一些场景中可以显著提高性能。

怎么计算出一个对象的内存占用?

计算为:对象头占用12字节,每个long类型占用3个字节,byte类型占用1个字节,合计字节数?34.再按照4个字节对齐原则?36

对象头:标记字(占用一个机器字,也就是8字节)、类型指针(占用一个机器字,也就是8字节;如果堆内存小于32G,JVM默认会开启指针压缩,则只占用4个字节)所以我说对象头占用12个字节 如果是数组,对象头还会多出一部分:数组长度,int 占用4字节

java 会存在内存泄漏吗?

内存泄漏是指不再被使用的对象或变量一直被占据在内存中。理论上java有GC垃圾回收机制的,也就是说不在被使用的对象,会被GC自动回收掉,自动从内存中清除掉/ 但是,java也是存在内存泄漏的情况的,java导致内存泄漏的原因很简单:长生命周期的对象持有段生命 周期的对象引用就可能造成内存泄漏,尽管短生命周期对象已经不需要了,但是因为长生命周期对象持有它的 引用而导致不能被回收。这就是java中内存泄漏的发生场景。