Java面试-第十九部分答案

194+195+196+197

 

Java虚拟机主要分为以下五个区: 
一、方法区(METHOD AREA): 
1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载 
2. 方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。 
3. 该区域是被线程共享的。 
4. 方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。

5.个人理解的方法区就是封装了一个java class 的所有信息

二、堆 (HEAP)
java堆是所有线程所共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都在这里创建,因此该区域经常发生垃圾回收操作。

三、虚拟机栈(JAVA STACK): 
1. 虚拟机栈也就是我们平常所称的栈内存,它为java方法服务,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接和方法出口等信息。 
2. 虚拟机栈是线程私有的,它的生命周期与线程相同。 
3. 局部变量表里存储的是基本数据类型、returnAddress类型(指向一条字节码指令的地址)和对象引用,这个对象引用有可能是指向对象起始地址的一个指针,也有可能是代表对象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间确定 
4.操作数栈的作用主要用来存储运算结果以及运算的操作数,它不同于局部变量表通过索引来访问,而是压栈和出栈的方式 
5.每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接.动态链接就是将常量池中的符号引用在运行期转化为直接引用。

四、本地方法区 (NATIVE METHOD STACK)
本地方法区和虚拟机栈类似,只不过本地方法栈为Native方法(对非java语言调用的接口)服务。

五、程序计数器 (PEOGRAM COUNTER REGISTER)
内存空间小,字节码解释器工作时通过改变这个计数值可以选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理和线程恢复等功能都需要依赖这个计数器完成。该内存区域是唯一一个java虚拟机规范没有规定任何OOM情况的区域。

 

 当一个classLoder启动的时候,classLoader的生存地点在jvm中的堆,然后它会去主机硬盘上将A.class装载到jvm的方法区,方法区中的这个字节文件会被虚拟机拿来new A字节码(),然后在堆内存生成了一个A字节码的对象,然后A字节码这个内存文件有两个引用一个指向A的class对象,一个指向加载自己的classLoader,

198.什么是双亲委派模型?

定义

双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。

双亲委派模型的工作过程是:

  • 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。
  • 每一个层次的类加载器都是如此。因此,所有的加载请求最终都应该传送到顶层的启动类加载器中。
  • 只有当父加载器反馈自己无法完成这个加载请求时(搜索范围中没有找到所需的类),子加载器才会尝试自己去加载。

很多人对“双亲”一词很困惑。这是翻译的锅,,,“双亲”只是“parents”的直译,实际上并不表示汉语中的父母双亲,而是一代一代很多parent,即parents。

作用

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。因此,使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处:类随着它的类加载器一起具备了一种带有优先级的层次关系。

例如类java.lang.Object,它由启动类加载器加载。双亲委派模型保证任何类加载器收到的对java.lang.Object的加载请求,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。

相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并用自定义的类加载器加载,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

199.类加载的执行过程

分为3个步骤:加载,链接,初始化,

加载:类的class文件读到内存中,系统创建一个java.lang.class对象,

链接(把类的二进制数据合并到JRE中去):又分为3个小步骤-----验证(文件格式验证,符号引用验证,元数据验证,字节码验证),准备,解析 (把二进制编码中的符号引用转变为直接引用)

初始化:把静态变量的真正的值初始化给变量,private static int a = 10;链接过程中,int a=0,初始化过程中,才是int a =10;

参考文献:https://blog.csdn.net/m0_38075425/article/details/81627349

200.怎么判断对象是否可以被回收?

利用根搜索算法,Reference chain机制,根节点是GC roots,然后其他的类object 1..2..n自顶向下,被GC roots关联起来,如果有类对象不被GC roots关联,我们可以说这个对象是可以被回收的;关键是GC roots的定义,一是虚拟机栈的引用对象,二是全局static变量引用对象,三是JNI技术中的Native方法(例如HashCode()方法),四是常量引用对象;

参考文献:https://blog.csdn.net/weixin_28760063/article/details/81271827

201.Java中有哪些引用类型?

4中引用类型,引用强度从大到小依次是强软弱虚;

强引用:就是直接new一个 对象引用,-----宁愿抛出OOM异常也不会回收的对象,容易造成内存溢出的引用类型;

软引用:new SoftReference<>(obj)对象引用;-----堆使用率达到阈值才回收;

弱引用:new weakReference<>(obj)对象引用;-----发现就回收;

虚引用:new PhantomReference<>()对象引用;  -----回收;

202.有哪些垃圾回收算法?

一是标记清除算法: 第一轮内存中的对象全部标记,第二轮内存中活动的对象清除标记,剩下的对象全部回收掉;

二是复制算法:内存分为From区和To区,第一轮在对象在from区分配内存,第二轮把from区对象全部复制到to区,from区清空,然后交换两个区的职责(一次GC);

三是引用计数算法:给每个对象加上一个计数器,每次引用对象计数器就+1,结束对象引用计数器-1,直到计数器为0的时候,回收该对象;

参考文献:https://blog.csdn.net/alpha_paser/article/details/81777936

203.jvm有哪些垃圾收回器?

新生代收集器:Serial、ParNew、Parallel Scavenge

老年代收集器:CMS、Serial Old、Parallel Old

CMS垃圾回收器:利用的是标记清除算法,

整堆收集器: G1

参考文献:https://www.cnblogs.com/chenpt/p/9803298.html

207.JVM调优工具有哪些?

 目前只谈JVM自带的工具:

jps:虚拟机进程状态查询工具

jhat:堆转存快照分析工具

jmap:java内存印象工具

jstack:堆栈跟踪工具

jinfo:java配置信息工具

jstat:统计信息监视工具

参考文献:https://www.cnblogs.com/warehouse/p/9479104.html

原文地址:https://www.cnblogs.com/zhzJAVA11/p/11518975.html