一、Java代码的运行步骤
一段Java代码先会被反编译为Java字节码,当执行java命令时,JVM虚拟机会被创建出来,并会创建一个main主线程来执行主方法。
二、JVM的内存结构有哪些?
1、方法区:(线程共享)
方法区用于读取类的原始信息(类的名字、继承关系、成员变量、引用的其他类的名字、类的方法代码)到内存中。例如Main、Student类
2、堆:(线程共享)
新建的对象(实例)会存储在堆中。
3、程序计数器:(线程私有)
用于记录代码执行到了第几行。
4、虚拟机栈:(线程私有)
用于存储局部变量和方法参数以及普通的java方法。
5、本地方法栈:(线程私有)
用于存储java本地方法。使用本地方法需要通过本地接口去调用本地库(由操作系统提供的一些功能)
6、注意:
在我们常用的Oracle虚拟机中,java本地方法(java代码不能自己实现,要借助操作系统的函数)和普通的java方法(java代码自己实现的方法)都是存储在虚拟机栈中的,本地方法栈并没有被实现。
三、执行引擎
1、垃圾回收(GC)
当变量没有被引用时,会被认定为垃圾,当虚拟机内存不足时被回收。
2、解释器
将字节码解释为机器码
3、即时编译器(JIT)
对调用频繁的代码,jit会将其的机器码缓存在内存中,效率成倍提高
四、哪些地方会产生内存溢出
1、出现OutOfMemoryError的情况
- 堆内存耗尽–对象越来越多,又一直在使用,不能被垃圾回收
- 方法区内存耗尽–加载的类越来越多,很多框架都会在运行期间动态产生新的类
- 虚拟机栈累积–每个线程最多会占用1M内存,线程个数越来越多,而又长时间运行不销毁时
2、出现StackOverflowError的区域
虚拟机栈内部–方法调用次数过多
不会出现内存溢出的区域–程序计数器