jdk jre jvm

1.jre:java运行环境,没有任何开发工具,包含jvm标准和java核心类库

jdk:软件开发工具包,在JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib合起来就称为jre。

2.运行时的数据区域:

java内存模型


1.java堆:虚拟机启动时创建,被所有线程共享

作用:存放对象实例以及数组(数组的引用存放在java栈中),垃圾收集器主要是管理java堆

2.栈:帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池

局部变量表中基本数据类型,局部变量存放的地方,引用类型的变量,存放的是指向对象的引用

指向运行时常量池的引用,因为在方法执行的过程中有可能需要用到类中的常量,所以必须要有一个引用指向运行时常量

线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈,所以在写程序使用递归算法时容易内存溢出

例子:

Object obj =  new  Object();

Object object:如果在方法体中出现,则存放到栈中;

new Object():在java堆中形成了一块存储Object类型所有对象实例数据值的内存,还包含对象内存的地址信息

3.程序计数器:

在JVM中,多线程是通过线程轮流切换来获得CPU执行时间的,因此,在任一具体时刻,一个CPU的内核只会执行一条线程中的指令,因此,为了能够使得每个线程都在线程切换后能够恢复在切换之前的程序执行位置,每个线程都需要有自己独立的程序计数器,并且不能互相被干扰

其中,程序计数器、栈(虚拟机栈和本地方法栈)两部分的内存随线程而生,随线程而灭。直接内存又称对外内存,不是由JVM负责管理的

3.如何判断对象是否死去?

1.引用计数法

给对象添加一个引用计数器,每当有一个地方引用他计数器加1,引用失效计数器减一,当计数器为0对象不再被使用

缺点:如果两个对象都不再使用,但是他们互相引用计数器不为0,无法回收

2.根搜索法

设立若干个跟对象,当任何一个根对象到某一个对象都无法到达的时候,这个对象可以回收。


如果是计数器算法则D与E都没有办法回收,但根搜索法GC root无法到达D与E,则不被使用可以回收

可作为root的对象:

1.栈中引用的对象

2 方法区中类静态属性引用的对象; 

3. 方法区中常量引用的对象; 

4.三种垃圾搜索算法

1.标记清除算法

通过根节点标记所有从根节点可达的对象,未被标记的为垃圾对象,清除阶段清除

当堆内有效空间被耗尽的时候停止整个程序进行两项工作 1.标记2.清除

必须要停止整个程序:我们刚标记完某个对象,暂且记为A,结果此时在程序当中又new了一个新对象B,且A对象可以到达B对象。但是由于此时A对象已经标记结束,B对象此时的标记位依然是0,因为它错过了标记阶段。因此当接下来轮到清除阶段的时候,新对象B将会被苦逼的清除掉。如此一来,不难想象结果,GC线程将会导致程序无法正常工作

缺点:效率比较低

2.复制算法

内存空间分为两块,使用一块,当进行垃圾回收时将正在使用内存中存活的对象复制到另一块内存中,清除正在使用内存块中的对象,之后交换两个内存的角色。

缺点:内存浪费,对象存活率较高时进行较多复制操作

3.标记-整理算法

从根节点开始,对所有可达节点做标记,清除未标记节点之后,将所有存活的对象压缩到一端,之后清除边界外所有空间

效率低:不仅要标记所有存活对象,还要整理所有存活对象的引用地址。从效率上来说,标记/整理算法要低于复制算法

4.分代收集算法

短命对象:新生代 适合复制算法

长命对象:老年代适合标记清理标记整理算法

5.类加载过程

每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑,这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件,”.class”文件中保存着Java代码经转换后的虚拟机指令,当需要使用某个类时,虚拟机将会加载它的”.class”文件,并创建对应的class对象,将class文件加载到虚拟机的内存,这个过程称为类加载

class文件描述的信息需要加载到虚拟机里面才能运行,虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制


1.加载

类加载过程的一个阶段:通过一个类的完全限定查找此类字节码文件,并利用字节码文件创建一个Class对象

验证

验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在堆中。其次,这里所说的初始值“通常情况”下是数据类型的零值


猜你喜欢

转载自blog.csdn.net/hewenjing8168/article/details/80826239