目录
JVM的作用:
jvm承担了java字节码的分析和执行,同时也内置了内存的分配和管理机制,此机制降低了研发人员手动分配和回收内存时可能带来的内存泄漏和内存溢出风险,使我们能更专注与业务和逻辑的实现.
JVM中的内存模型:
1.堆内存(heap):
是jvm内存中最大一块内存空间,堆内存被所有线程共享,几乎所有的对象和数组都被分配到堆内存中;堆被划分为新生代和老年代,新生代又分为eden区和survivor区.
java8为什么用元空间取代java7中的永久代?
永久代的内存经常不够用或发生内存溢出,爆出java.lang.OutOfMemoryError:PermGen的问题,这是因为jdk1.7版本中,给PermGen分配多大的空间又很难确定, 而PermGen区的指定内存大小仅为8M,永久代内的元数据回收率又偏低,所以性能不令人满意.
2.程序计数器:
是一个很小的内存空间,主要用来记录各线程执行的字节码的地址,例如:分支,循环,跳转,异常,线程恢复等都依赖于计数器.
由于java是多线程语言,当执行的线程数量超过CPU数量时,线程之间会根据轮转的时间片来争夺CPU资源,当一个线程的时间片用完或者因为其他原因导致该线程的CPU资源被提前剥夺,那么该线程就会是使用一个程序计数器,来记录该线程下一条执行的指令,类似于现场快照,方便下次被调度时快速恢复执行现场.
3.方法区:
主要用来存放已被虚拟机加载的类相关的信息,包括类信息,运行时的常量池,字符串常量池等.
4.虚拟机栈(VM stack)
java虚拟机栈是线程私有的内存空间,随java线程一起创建,在创建一个线程时,会再虚拟机中申请一个线程栈,用来保存方法的局部变量,操作数栈,动态链接方法和返回地址等信息.
5.本地方法栈:
本地方法栈跟java虚拟机栈功能类似,java虚拟机栈用于管理函数的调用,而本地方法栈则用于管理本地方法的调用,但本地方法并不是java实现的,而是由C语言实现的.
java代码是如何在jvm中运行的?
.java文件经javac编译成.class格式的字节码文件,字节码只能在JVM中运行,JVM加载字节码,然后在JVM中将字节码再编译成机器码,这样计算机就可识别并执行指令.
JVM运行原理:
1.jvm向操作系统申请内存,根据内存大小找到具体的内存分配表,然后把内存段的起始地址和终止地址分配给JVM.
2.JVM获得内存空间后,再根据配置参数分配堆,栈以及方法区的内存大小.
3.class文件开始加载,验证,解析,其中准备阶段会为类的静态变量分配内存,完成初始化一些列系统的初始化工作.
4.执行方法,创建main线程,在main线程中执行main方法,在执行时会再堆中创建对象,并把对象的引用存放在栈中.