JVM

JVM

阿里二面试题:JVM 方法区和元空间什么关系?6大角度带你了解方法区

阿里二面:JVM方法区和元空间的关系到底是怎样的

方法区和永久代以及元空间有什么关系?

方法区和永久代以及元空间的关系很像 Java 中接口和类的关系,类实现了接口,这里的类就可以看作是永久代和元空间,接口可以看作是方法区,也就是说永久代以及元空间是 HotSpot 虚拟机对虚拟机规范中方法区的两种实现方式。

并且,永久代是 JDK 1.8 之前的方法区实现,JDK 1.8 及以后方法区的实现便成为元空间。

JDK 1.7 为什么要将字符串常量池移动到堆中?

主要是因为永久代(方法区实现)的 GC 回收效率太低,只有在整堆收集 (Full GC)的时候才会被执行 GC。Java 程序中通常会有大量的被创建的字符串等待回收,将字符串常量池放到堆中,能够更高效及时地回收字符串内存。

注意

Java的堆中 1.8及以后有new出来的对象实例,静态变量、字符串常量池

而1.6及以前静态变量和字符串常量池都是在方法去中(永久带中)。

0acb7c38c148e32c78451ff7a9cbe5f3.webp.png

Screen-Shot-2022-06-13-at-16.06.01.png

JVM内存结构、内存模型、对象模型的区别

  1. JVM内存结构和Java虚拟机运行时区域有关。
  2. Java内存模型和Java并发编程有关。
  3. Java对象模型和Java对象在虚拟机中表现形式有关。

JMM定义了一套在多线程读写共享数据时(成员变量,数组)时,对数据的可见性、有序性、和原子性的规则和保障

Jvm知识

里面有GC、调优等等

GC

JVM: 垃圾回收

一道关于GC的题目

kRD15MXms9buY7h

jdk创建对象的速度远大于cglib,这是由于cglib创建对象时需要操作字节码。cglib执行速度略大于jdk,所以比较适合单例模式。另外由于CGLIB的大部分类是直接对Java字节码进行操作,这样生成的类会在Java的永久堆中。如果动态代理操作过多,容易造成永久堆满,触发OutOfMemory异常。spring默认使用jdk动态代理,如果类没有接口,则使用cglib。

选C

CGLIB是一个强大的、高性能的代码生成库。

CGLIB代理主要通过对字节码的操作,为对象引入间接级别,以控制对象的访问。我们知道Java中有一个动态代理也是做这个事情的,那我们为什么不直接使用Java动态代理,而要使用CGLIB呢?答案是CGLIB相比于JDK动态代理更加强大,JDK动态代理虽然简单易用,但是其有一个致命缺陷是,只能对接口进行代理。如果要代理的类为一个普通类、没有接口,那么Java动态代理就没法使用了。

CGLIB和Java动态代理的区别

  1. Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承);CGLIB能够代理普通类;
  2. Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效

CMS垃圾回收器存在的问题及解决方案

hMOlustCV2EJQIK

空间碎片问题
由于CMS使用的是标记-清理算法,因此会导致产生大量的内存碎片,如果不整理的话,将会有大量的不连续的内存空间存在,因此就无法存放大对象,导致频繁GC。
解决方案:
CMS存在一个默认的参数 “-XX:+UseCMSCompactAtFullCollection”,意思是在Full GC之后再次STW,停止工作线程,整理内存空间,将存活的对象移到一边。
还有一个参数是“-XX:+CMSFullGCsBeforeCompaction”,表示在进行多少次Full GC之后进行内存碎片整理,默认为0,即每次Full GC之后都进行内存碎片整理。

c25VQSdEOLl9CKh

这题应该选a吧,还能加入队列啊。而且也不一定是old的那个策略啊。

Author: Jcwang

Permalink: http://example.com/2022/06/13/JVM/