JVM基础面试题及原理讲解

  • 时间:
  • 浏览:0

Java创建对象过程

 */

String str1 = "str";

7

Integer i11 = 333;

Java 堆是垃圾分类分类整理器管理的主要区域,如可让 也被称作GC堆(Garbage Collected Heap).从垃圾回收的深度图,将会现在分类分类整理器基本都采用分代垃圾分类分类整理算法,全都Java堆还还上能 细分为:新生代和老年代:再细致如可让 有:Eden空间、From Survivor、To Survivor空间等。进一步划分的目的是更好地回收内存,将会调慢地分配内存。

2

有有哪些组成次要如可让 是系统应用应用程序私有的,如可让 的则是系统应用应用程序共享的。

验证:

1

6

5

直接内存是否而是是虚拟机运行时数据区的一次要,全都是虚拟机规范中定义的内存区域,如可让 这次要内存也被频繁地使用。如可让 也将会原困OutOfMemoryError异常突然突然出现。

3. 初始化零值: 内存分配完成后,虚拟机还要将分配到的内存空间都初始化为零值(不包括对象头),两种步操作保证了对象的实例字段在 Java 代码中还上能 不赋初始值就直接使用,系统应用应用程序能访问到有有哪些字段的数据类型所对应的零值。

1

5

3

5. 执行 init 土最好的法子: 在上端工作都完成以后 ,从虚拟机的视角来看,有一一还还有一个新的对象将会产生了,但从 Java 系统应用应用程序的视角来看,对象创建才以后以后开始英文,<init> 土最好的法子还没哟执行,所有的字段都还为零。全都一般来说,执行 new 指令以后 会接着执行 <init> 土最好的法子,把对象按照系统应用应用程序员的意愿进行初始化,另有一一还还有一个有一一还还有一个真正可用的对象才算删改产生出来。

Java 虚拟机栈会突然突然出现两种异常:StackOverFlowError 和 OutOfMemoryError。

System.out.println("40=i5+i6   " + (40 == i5 + i6));

2

System.out.println("i4=i5+i6   " + (i4 == i5 + i6));  

9

System.out.println(s3 == s2);

3

4. 设置对象头: 初始化零值完成以后 ,虚拟机要对对象进行必要的设置,类事两种对象是那个类的实例、如可不能找到类的元数据信息、对象的哈希吗、对象的 GC 分代年龄等信息。 有有哪些信息存贴到 对象头中。 另外,根据虚拟机当前运行情形的不同,如是否启用偏向锁等,对象头会有不同的设置土最好的法子。

Integer i1 = 40;

推荐阅读:Java8内存模型——永久代(PermGen)和元空间(Metaspace)

/**

        return IntegerCache.cache[i + (-IntegerCache.low)];

8

Integer i2 = new Integer(40);

9

Integer i3 = 0;

System.out.println(str3 == str5);

注意:系统应用应用程序计数器是唯不要突然突然出现 OutOfMemoryError 的内存区域,它的生命周期随着系统应用应用程序的创建而创建,随着系统应用应用程序的以后以后开始而死亡。

通过句柄访问对象

System.out.println("i1=i4   " + (i1 == i4));

解释:

建立对象全都为了使用对象,亲戚亲戚大家儿的Java系统应用应用程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问土最好的法子有虚拟机实现而定,目前主流的访问土最好的法子有使用句柄和直接指针两种:

Java 虚拟机所管理的内存中最大的一块,Java 堆是所有系统应用应用程序共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的全都存放对象实例,几乎所有的对象实例以及数组是否这里分配内存。

HotSpot 虚拟机中土最好的法子区也常被称为 “永久代”,本质上两者是否而是等价。仅仅是将会 HotSpot 虚拟机设计团队用永久代来实现土最好的法子区而已,另有一一还还有一个 HotSpot 虚拟机的垃圾分类分类整理器就还上能 像管理 Java 堆一样管理这次要内存了。如可让 这是否而是是有一一还还有一个好主意,将会另有一一还还有一个更容易遇到内存溢出现象。

System.out.println(str3 == str4);

土最好的法子执行完毕后相应的栈帧也会出栈并释放内存空间,也会突然突然出现 StackOverFlowError 和 OutOfMemoryError 两种异常。

确定以上两种土最好的法子中的哪两种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 分类分类整理器的算法是”标记-清除”,还是”标记-分类整理”(也称作”标记-压缩”),值得注意的是,群克隆算法内存也是规整的。

3 String 字符串拼接

2

String s3 = "计算机";

5

在 JDK 1.8中移除整个永久代,取而代之的是有一一还还有一个叫元空间(Metaspace)的区域(永久代使用的是JVM的堆内存空间,而元空间使用的是物理内存,直接受到本机的物理内存限制)。

尽量处理多个字符串拼接,将会另有一一还还有一个会重新创建对象。将会还要改变字符串一句话,还上能 使用 StringBuilder 将会 StringBuffer。

String str5 = "string";

4

Integer 比较(==)更丰厚的有一一还还有一个例子:

3

2. 分配内存: 在类加载检查通以后 ,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。分配土最好的法子有 “指针碰撞” 和 “空闲列表” 两种,确定那种分配土最好的法子由 Java 堆是否规整决定,而Java堆是否规整又由所采用的垃圾分类分类整理器是否中有 压缩分类整理功能决定。

2 String 类型的常量池比较特殊。它的主要使用土最好的法子有两种:

创建了有一一还还有一个对象。

5

i1=i2+i3   true

通过直接指针访问对象

1

4

String str2 = "ing";

内存分配并发现象(补充内容,还要掌握)

本地土最好的法子被执行的以后 ,在本地土最好的法子栈也会创建有一一还还有一个栈帧,用于存放该本地土最好的法子的局部变量表、操作数栈、动态链接、出口信息。

和虚拟机栈所发挥的作用非常类事,区别是: 虚拟机栈为虚拟机执行 Java 土最好的法子 (也全都字节码)服务,而本地土最好的法子栈则为虚拟机使用到的 Native 土最好的法子服务。 在 HotSpot 虚拟机中和 Java 虚拟机栈合二为一。

推荐阅读:Java 中几种常量池的区分

1

Integer i22 = 333;

String str4 = str1 + str2;

6

Double i3 = 1.2;

3

String s1 = new String("abc");

i4=i5+i6   true

Integer i1 = 33;

3

8

本机直接内存的分配不要收到 Java 堆的限制,如可让 ,既然是内存就会受到本机总内存大小以及处理器寻址空间的限制。

2

String str1 = "abcd";

既然运行时常量池时土最好的法子区的一次要,自然受到土最好的法子区内存的限制,当常量池无法再申请到内存是否抛出 OutOfMemoryError 异常。

系统应用应用程序共享的:

6

1. 句柄: 将会使用句柄一句话,没哟 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的全都对象的句柄地址,而句柄中中有 了对象实例数据与类型数据人及的具体地址信息。

Hotspot虚拟机的对象头包括两次要信息,第一次要用于存储对象自身的自身运行时数据(哈希码、GC分代年龄、锁情形标志等等),另一次而是类型指针,即对象指向它的类元数据的指针,虚拟机通过两种指针来确定两种对象是那个类的实例。

System.out.println("i4=i5   " + (i4 == i5));

1 String 对象的两种创建土最好的法子

Integer i6 = new Integer(0);

9

String str3 = "str" + "ing";

3

String s1 = new String("abc");

System.out.println(i11 == i22);

System.out.println(s2);

土最好的法子区与 Java 堆一样,是各个系统应用应用程序共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。其实 Java虚拟机规范把土最好的法子区描述为堆的有一一还还有一个逻辑次要,如可让 它却有有一一还还有一个别全名是做 Non-Heap(非堆),目的应该是与 Java 堆区分开来。

在 Hotspot 虚拟机中,对象在内存中的布局还上能 分为3块区域:对象头、实例数据和对齐填充。

4

Integer i2 = 40;

这两种不同的创建土最好的法子是有差别的,第两种土最好的法子是在常量池中拿对象,第二种土最好的法子是直接在堆内存空间创建有一一还还有一个新的对象。

记住:只要使用 new 土最好的法子,便还要创建新的对象。

局部变量表主要存放了编译器可知的各种数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不同于对象两种,将会是有一一还还有一个指向对象起始地址的引用指针,也将会是指向有一一还还有一个代表对象的句柄或如可让 与此对象相关的位置)。

    return new Integer(i);

先有字符串 “abc” 贴到 常量池,如可让 new 了一份字符串 “abc” 贴到 Java 堆(字符串常量 “abc” 在编译期就将会确定贴到 常量池,而 Java 堆上的 “abc” 是在运行期初始化阶段才确定),如可让 Java 栈的 str1 指向 Java 堆上的 “abc”。

System.out.println(i3 == i4);

解释:

public static Integer valueOf(int i) {

实例数据次而是对象真正存储的有效信息,也是在系统应用应用程序中所定义的各种类型的字段内容。

Integer i1 = 40;

从上端的介绍中亲戚亲戚大家儿知道系统应用应用程序计数器主要有有一一还还有一个作用:

System.out.println("i1=i2   " + (i1 == i2));

1

7

2

System.out.println(s1 == s2);

2

Java 虚拟机栈也是系统应用应用程序私有的,每个系统应用应用程序是否人及的Java虚拟机栈,如可让 随着系统应用应用程序的创建而创建,随着系统应用应用程序的死亡而死亡。

2

10

System.out.println(i1==i2);

4

应用场景:

 *此土最好的法子将始终缓存-128到127(包括端点)范围内的值,不还上能 缓存此范围之外的如可让 值。

系统应用应用程序计数器是一块较小的内存空间,还上能 看作是当前系统应用应用程序所执行的字节码的行号指示器。字节码解释器工作时通过改变两种计数器的值来确定下三根还要执行的字节码指令,分支、循环、跳转、异常处理、系统应用应用程序恢复等功能都还要依赖两种计数器来完。

通过上端的介绍亲戚亲戚大家儿离米 知道了虚拟机的内存情形,下面亲戚亲戚大家儿来删改的了解一下 HotSpot 虚拟机在 Java 堆中对象分配、布局和访问的全过程。

4

Java 内存还上能 粗糙的区分为堆内存(Heap)和栈内存(Stack)其中栈全都现在说的虚拟机栈,将会说是虚拟机栈中局部变量表次要。 (实际上,Java虚拟机栈是由有一一还还有一个个栈帧组成,而每个栈帧中都拥有局部变量表、操作数栈、动态链接、土最好的法子出口信息)

3

系统应用应用程序私有的:

与系统应用应用程序计数器一样,Java虚拟机栈也是系统应用应用程序私有的,它的生命周期和系统应用应用程序相同,描述的是 Java 土最好的法子执行的内存模型。

6

}

7

String s1 = new String("计算机");

Double i4 = 1.2;

运行时常量池是土最好的法子区的一次要。Class 文件中除了有类的版本、字段、土最好的法子、接口等描述信息外,还有常量池信息(用于存放编译期生成的各种字面量和符号引用)

1

对齐填充次要是否必然占据 的,也没哟有哪些特别的含义,仅仅起占位作用。 将会 Hotspot 虚拟机的自动内存管理系统要求对象起始地址还而是8字节的整数倍,换句话说全都对象的大小还而是8字节的整数倍。而对象头次要正好是8字节的倍数(1倍或2倍),如可让 ,当对象实例数据次要没哟对齐时,就还要通过对齐填充来补全。

1

System.out.println(s1 == s2);

结果:

4

7

另外,为了系统应用应用程序切换还上能 恢复到正确的执行位置,每条系统应用应用程序都还要有有一一还还有一个独立的系统应用应用程序计数器,各系统应用应用程序之间计数器互不影响,独立存储,亲戚亲戚大家儿称类事内存区域为“系统应用应用程序私有”的内存。

String str2 = new String("abcd");

5

5

JDK1.4中新加入的 NIO(New Input/Output) 类,引入了两种基于通道(Channel) 与缓存区(Buffer) 的 I/O 土最好的法子,它还上能 直接使用Native函数库直接分配堆外内存,如可让 通过有一一还还有一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。另有一一还还有一个就能在如可让 场景中显著提高性能,将会处理了在 Java 堆和 Native 堆之间来回群克隆数据。

3

11

一句话 i4 == i5 + i6,将会 + 两种操作符不适用于 Integer 对象,首先 i5 和 i6 进行自动拆箱操作,进行数值相加,即 i4 == 40。如可让 Integer对象无法与数值进行直接比较,全都i4自动拆箱转为int值40,最终这条一句话转为40 == 40进行数值比较。

Integer i2 = 33;

1

System.out.println(str1==str2);

Integer i4 = new Integer(40);

对于 Java 系统应用应用程序员来说,在虚拟机自动内存管理机制下,不再还要像C/C++系统应用应用程序开发系统应用应用程序员另有一一还还有一个为内有一一还还有一个 new 操作去写对应的 delete/free 操作,不容易突然突然出现内存泄漏和内存溢出现象。正是将会 Java 系统应用应用程序员把内存控制权利交给 Java 虚拟机,一旦突然突然出现内存泄漏和溢出方面的现象,将会不了解虚拟机是如可使用内存的,没哟排查错误将会是有一一还还有一个非常艰巨的任务。

Integer 缓存源代码:

下图便是 Java 对象的创建过程,我建议最好是能默写出来,如可让 要掌握每一步在做有哪些。

i1=i4   false

1

在创建对象的以后 有有一一还还有一个特别要的现象,全都系统应用应用程序安全,将会在实际开发过程中,创建对象是很频繁的事情,作为虚拟机来说,还要要保证系统应用应用程序是安全的,通常来讲,虚拟机采用两种土最好的法子来保证系统应用应用程序安全:

12

13

6

String s2 = s1.intern();

JDK1.7及以后 版本的 JVM 将会将运行时常量池从土最好的法子区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。

System.out.println(str4 == str5);

8

2

System.out.println(i1 == i2);

4

这两种对象访问土最好的法子各有优势。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 两种不还要修改。使用直接指针访问土最好的法子最大的好处全都速率快,它节省了一次指针定位的时间开销。

    if (i >= IntegerCache.low && i <= IntegerCache.high)

i4=i5   false

相对而言,垃圾分类分类整理行为在两种区域是比较少突然突然出现的,但是否而是数据进入土最好的法子区后就“永久占据 ”了。

内存分配的两种土最好的法子:(补充内容,还要掌握)

2. 直接指针: 将会使用直接指针访问,没哟 Java 堆对象的布局中就还要考虑如可放置访问类型数据的相关信息,而 reference 中存储的直接全都对象的地址。

2

1. 类加载检查: 虚拟机遇到三根 new 指令时,首先将去检查两种指令的参数是否能在常量池中定位到两种类的符号引用,如可让 检查两种符号引用代表的类是否已被加载过、解析和初始化过。将会没哟,那还要先执行相应的类加载过程。

Integer i5 = new Integer(40);

System.out.println(s1.equals(s2));

本文从 JVM 形状入手,介绍了 Java 内存管理、对象创建、常量池等基础知识,对面试中 JVM 相关的基础题目进行了讲解。

40=i5+i6   true

i1=i2   true

String s2 = "abc";

8

6

1

结果:

System.out.println("i1=i2+i3   " + (i1 == i2 + i3));

3

Java 虚拟机在执行 Java 系统应用应用程序的过程中会把它管理的内存划分成若干个不同的数据区域。