哈尔版网站建设河源网站seo
什么是 Java 内存结构
Java 内存结构就是 JVM 的运行书数据区的内存结构:
里面有堆、虚拟机栈、本地方法栈、程序计数器;
虚拟机栈:里面的数据结构是栈帧,存放了方法名,局部变量等信息
方法区在 1.8 的时候,被元空间代替掉了,产量池放到了堆中,类的原信息放到了直接内存中
什么是 Java 内存模型
Java 内存模型是为了保证 Java 程序在多线程运行下,仍然可以使得数据安全性,这里的安全指的是线程安全,也就是保证数据的,可见性、有序性、原子性。
为了使得 Java 内存模型的实现,设计了一系列的关键字,比如:synchornized volatile final
除此之外,还涉及了 happen - before 原则:
线程的执行在线程的创建之后,
线程中前面的动作再早于后面的执行动作,
通过设计了一系列的规则,保证的多线程下面的线程安全问题
堆和栈之间的区别是什么?
堆:在 JVM 的内存结构中,主要的作用就是存储 Java 对象,是一块比较大的内存空间
栈:存放的数据结构主要是栈帧,里面保存了方法以及方法调用之间的关系,是一块内存空间比较小的区域。
从内存的分配方式来看:栈的空间是 JVM 自动分配的,但是堆空间的话,需要开发人员使用 new 关键字主动的创建对象。
什么情况下可能发生栈溢出的情况?
栈中的内存空间是有一定限制的,如果方法调用的非常多,那么是有可能发生栈溢出的,比如使用递归调用。
什么是 OutOfMemory ,怎么解决 OOM 问题
在堆内存空间会申请内存创建对象,如果在尝试请求的时候没有申请到这个内存空间的话,那么就会发生 OOM 的异常。
分析的思路就是:既然发生了这个现象,不是考虑背什么东西,而是分析内存空间中发生了什么?是不是有大对象的存在没有及时的被回收?是不是某些代码中重复的创建大量的相同对象?
当然,可以使用一些工具来查看在 JVM 中各个年代的对象情况,内存占比情况,作出进一步的分析。
Java 常量池
在 Java 中,为了使得程序运行的效率在一定程度上得到提升,设计了常量池的概念,常量池的核心思想就是将已有的数据进行缓存,等到需要的时候,直接拿出来使用就行,避免再使用的时候没有数据再去创建的步骤。
Java 的常量池有:字符串常量池,String 类型的字符串常量池,还有 Integer 的常量池(缓存了 -128 ~ 127 之间的数据)
如何判断 Java 中的对象是不是存活的?
引用计数器方法:
如果有引用指向了对象,那么这个对象的的引用计数器数值 + 1;一直到这个计数器为 0 的时候,这个对象就可以回收了,但是容易出现内存泄、、的风险,如果两个没有作用的对象是互相引用的话,那么就会出现内存泄露。
可达性分析算法
在 Java 中定义了 GC Root 对象,如果一个对象到 GC Roots 是可达的,那么这个对象就不用被回收,如果不可达的话,那么这个对象就可以被回收了。
常见的 GC Roots 对象就是虚拟机栈或者本地方法栈中引用的对象。
总之,就是引用计数器和可达性分析, GC Roots 就是虚拟机栈或者本地方法栈中引用的对象。
Java 中的强引用、软引用、弱引用、虚引用
强:new 关键字直接引用的对象,一般是不会被回收的
软:只有 JVM 堆内存空间不够用的情况下,没有空间工体给新的对象的创建的时候,会回收这种对象
弱引用:会在下一次垃圾回收的时候,回收掉这个对象
虚引用:随时可能被回收掉的 Java 对象
JVM 的垃圾回收算法
标记 - 清除
标记 - 复制:将内存空间分为两份,将存活的对象移动到一边,然后清除另外一份的内存空间
标记 - 整理:将存活的对象整理到内存区域的一端,然后将边界之外的内存空间进行垃圾回收即可
注:在复制的时候,需要将内存区域划分为 2 块,一块保存存活对象,另外一份直接清理掉。在整理的时候,将存活的对象放到一端,将边界之外的对象全部清理掉。