其他资料
目录
10.String s = new String(“abc”)执行过程中分别对应哪些内存区域?
1.java是如何实现跨平台的?
Java 程序在编译后生成字节码(.class 文件),而不是直接生成特定于某一操作系统的机器代码。
在不同操作系统上都有各自实现的 JVM,负责将字节码翻译为特定平台的机器代码并执行。这使得同一份Java 字节码可以在任何支持 JVM的平台上运行。
2.JVM由哪些部分组成?
类加载器+运行时数据区+执行引擎+本地方法接口
通过类加载器把class文件加载到运行时数据区,但是操作系统无法识别class文件,又要用到执行引擎中的解释器翻译成对应的机器码去执行,这个过程可能会调用不同语言为java提供的接口,例如驱动,就会执行本地方法接口。
3.编译执行和解释执行的区别?
编译执行:是指程序在执行之前,首先通过编译器将源代码编译为机器代码,然后直接在 CPU 上运行。常见的编译语言如 C、C++。
·优点:编译后的程序运行速度快,因为机器代码是针对目标平台直接生成的,且不需要在运行时再进行翻译
·缺点:程序必须针对每个平台重新编译,跨平台性差;另外,编译后生成的机器代码难以调试和逆向工程。
解释执行:解释执行是指源代码不经过编译器的预先编译,而是在运行时通过解释器逐行翻译并执行。常见的解释语言如 Python、Ruby。
·优点:跨平台性好,因为代码在每个平台上都是通过相应平台的解释器来运行的,且开发周期更短。
·缺点:运行速度较慢,因为每次执行时都需要进行动态翻译和解释。
JVM 采用编译执行和解释执行相结合的方式
·解释执行:JVM 会逐行解释执行字节码,尤其是程序初次运行时,这种方式有助于程序的跨平台性。
即时编译(JIT):JVM 引入了即时编译器(Just-In-Time Compiler),在程序运行时将热代码(经常执行的代码)编译为本地机器码,避免反复解释,提升性能。因此,JVM 实际上是混合使用解释执行和编译执行。
以例子来理解就是编译执行就是把一篇英文文章一次性翻译成中文译文然后给你看,解释执行就是逐句翻译逐句理解,而JVM拿到字节码文件之后就是逐句翻译逐句理解,然后把经常阅读到的段落编译成中文“写在旁边”,避免反复翻译。
4.JVM的内存区域如何划分?
分为堆区、栈区、本地方法栈、程序计数器、方法区
堆区:用于存放对象。线程共享。
栈区:用于存放栈帧,每个方法对应一个栈帧。栈帧有局部变量表,操作数栈,动态链接,方法返回地址。线程私有。
本地方法栈:用于本地方法,通过JNI调用的方法在此区域分配内存。线程私有。
程序计数器:存储下一条要执行的指令的地址。线程私有。
方法区:存放类的元数据信息,例如类名,方法,字段等,还有JIT编译器编译之后的代码。线程共享。
1.8之前由永久代实现,1.8之后由元空间实现。
永久代:Full GC可以回收,但是回收的效率极低,可能频繁触发fullGC,因为永久代存储的数据是一些元数据信息。存在的时间一般很长,被回收的几率小。大小固定。很难设置一个合适的大小。元空间:元空间使用的是操作系统的直接内存,理论上其大小只受限于操作系统的内存限制,因此可以更有效地避免由于永久代空间不足而引发的FuIl GC问题。
5.JVM内存模型里的堆和栈有什么区别?
用途:栈主要用于存储局部变量、方法调用的参数、方法返回地址和一些临时数据。每当一个方法被调用,就会在栈中创建一个栈帧,用于存储该方法的信息,方法执行完毕,栈帧也被移除。堆用于存储对象的实例,当使用new关键字创建一个对象时,对象的实例会在堆中分配空间。
生命周期:栈中的数据具有确定的生命周期,当方法执行结束时,对应的栈帧会被销毁。而堆中的对象生命周期不确定,最终是由jvm的垃圾回收机制所回收。
存取速度:栈的存取速度通常比堆快,因为栈遵循着先进后出的原则,操作简单快速,而堆存取速度相对较慢。
存储空间:栈的空间相对较小且固定,由操作系统管理。堆的空间较大,动态扩展,由jvm管理。栈溢出一般是递归过深或局部变量过大,堆溢出一般是创建的对象过多,垃圾回收器回收不过来。
可见性:栈中的数据对线程是私有的,每个线程都有其局部变量。堆中的数据是共享的,可以由其他线程访问。
6.栈中存的到底是指针还是对象?
在JVM内存模型中,栈主要用于管理局部变量和方法调用上下文,堆用于存储所有类的实例和数组。
栈中存储的不是对象,是对象的引用。
7.堆分为哪几部分呢?
堆分为新生代和老年代,其中新生代占堆空间的三分之一,老年代占堆空间的三分之二。
新生代:分为Eden Space和Survivor Space,大多数新创建的对象首先存放在Eden Space,而Eden Space较小,满了之后会触发一次Minor GC,也就是新生代垃圾回收。在Minor GC下存活下来的对象会被移动到Survive Space,继续他们的生命周期。
老年代:存放经历多次Minor GC仍然存活的对象,老年代中的对象生命周期较长,因此Major GC发生频率较低,但执行时间比Minor GC长。
8.程序计数器的作用,为什么是私有的?
Java支持多线程一起运行,CPU会给每个线程分配一个时间片,在时间片内代码还没有执行完就会切换到另外一个线程执行代码,然后另外一个线程代码执行完毕或者时间片用完就会再切回原线程。在线程切换的过程就需要程序计数器来提供指令地址,每个线程的指令地址都是不一样的,因此每个线程都有其私有的程序计数器。
9.方法区中的方法的执行过程?
当程序调用方法的时候,Java虚拟机会根据方法的符号引用来找到实际的方法地址,然后在当前线程的虚拟机栈为该方法创建一个栈帧来存储方法的各种信息,之后就执行方法内的字节码指令,最后方法执行完毕,可能会返回结果,最终会移除掉栈帧。
10.String s = new String(“abc”)执行过程中分别对应哪些内存区域?
使用new关键字,因此创建的字符串对象是在堆内存上,JVM会先拿着abc去字符串常量池中尝试获取对应string对象的引用。如果在字符串常量池中不存在这个abc就会创建两个对象,一个是abc这个字符串常量,另一个是new string这个实例对象,如果abc存在就只会创建new string这个对象。