栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM相关知识

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM相关知识

1、类加载过程 

   加载——》连接——》初始化

  • 加载

    1)将类的字节码载入方法区,并创建类的.class对象

    2)如果此类的父类没有加载,会加载父类

    3)加载是懒惰执行

  • 连接

     1)验证:检查加载到的字节信息是否符合JVM规范

     2)准备:创建类或接口的静态变量,并赋初始值,半初始化状态

     3)解析:把常量池中的符号引用转为直接引用,建立连接。符号引用就是一些符号当被使用的时候转为直接引用

  •  初始化:

     1)执行静态代码块与非final静态变量的赋值

     2)初始化时懒惰执行

2、类加载器双亲委派模型

 JVM中存在三个默认的类加载器:

  1)BootstrapClassLoader:ExtClassLoader的父类加载器,默认负责加载%JAVA_HOME%lib下的jar包和class文件

  2)ExtClassLoader:AppClassLoader的父类加载器,负责加载%JAVA_HOME%/lib/ext文件夹下的jar包和class类

  3)AppClassLoader:自定义类加载器的父类,负责加载classpath下的类文件

 JVM在加载一个类时,会调用AppClassLoader的loadClass方法来加载这个类,其中在每次调用loadClass时会调用findLoadedClass()来判断缓存中是否有这个类,没有的话再使用ExtClassLoader 的loadClass方法来加载类,同样ExtClassLoader的loadClass方法中会先使用BootstrapClassLoader来加载类,如果BootstrapClassLoader加载到了就直接成功,如果没有加载到,那么ExtClassLoader就会自己尝试加载该类,如果没有还加载到,那么则会由AppClassLoader来加载这个类。

 所以,双亲委派指的是,JVM在加载类时,会委派给Ext和Bootstrap进行加载,如果没有加载到才会由自己加载。经典的一句话:向上委托加载,向下委托查找

3、JVM内存模型

 4、JVM中哪些是线程共享区 

 5、JVM中哪些可以作为gc root

 什么是gc root,JVM在进行垃圾回收时,需要找到"垃圾"对象,也就是没有被引用的对象,但是直接找"垃圾"对象是比较耗时的,所以反过来,先找"非垃圾"对象,也就是正常对象,java使用的是根可达算法,那么就需要从某些"根"开始去找,根据这些"根"的引用路径找到正常对象,而这些"根"有一个特征,就是它只会引用其他对象,而不会被其他对象引用,例如:栈中的本地变量、方法区中的静态变量、本地方法栈中的变量、正在运行的线程等可以作为gc root。 

 6、一个对象从加载到JVM,再到GC清除,都经历了什么过程

 1)用户创建对象,JVM首先需要到方法区去找对象的类型信息,然后再创建对象

 2)JVM要实例化一个对象,首先在堆中创建对象 ——》半初始化状态

 3)对象会分配在堆内存新生代的eden区,然后经历一次Minor GC,对象如果存活,就会进入S区,在后续的每次GC中,如果对象一直存活,就会在S区来回拷贝,每移动一次,年龄加一 

 ——多大年龄才会移入老年代?4比特,年龄最大15

 4)当方法执行结束后,栈中的指针会先移除掉

 5)堆中的对象,经过Full GC就会被标记为垃圾,然后被GC回收

7、JAVA中的引用类型有哪几种

 1)硬引用(撑爆了也不会回收)

 2)软引用(空间不够才会回收,特别适合做缓存)  SoftReference m = new SoftReference<>(new byte[1024*1024*10]);

 3)弱引用(看见就被回收)  WeakReference m = new WeakReference<>(new M());

 4)虚引用(虚引用是所有引用中最弱的一种引用,其存在就是为了将关联虚引用的对象在被GC掉之后收到一个通知。(不能通过get方法获得其指向的对象)堆外内存回收旧用到了这个虚引用)PhantomReference

8、ThreadLocal

  线程私有的,每次取值和赋值都会从自己线程的ThreadLocalMap。

9、进程?线程?

 1)进程:静态概念,分配资源

 2)线程

  • 动态概念 共享资源
  • 主线程

      第一个启动main线程

 进程是系统资源分配的基本单元

 线程是系统执行任务的基本单元

注意:线程是不是越多越好? 不是,太多的话cpu都会用在线程切换,执行任务的时间就少了

10、哪些部分会出现内存溢出

 不会出现内存溢出的区域——程序计数器

 出现OutOfMemoryError的情况

  1)堆内存耗尽—对象越来越多,又一直在使用,不能被垃圾回收

  2)方法区内存耗尽—加载的类越来越多,很多框架都会在运行期间动态产生新的类

  3)虚拟机栈累计—每个线程最多会占用1M内存,线程个数越来越多,而又长时间运行不销毁时

 出现StackOverflowError的区域

   虚拟机栈内部—方法调用次数过多

11、方法区与永久代、元空间之间的关系
  • 方法区是JVM规范中定义的一块内存区域,用来存储类型信息、常量、静态变量,即时编译器编译后的代码缓存等。
  • 永久代是Hopspot虚拟机对JVM规范的实现(1.8之前)
  • 元空间是Hopspot虚拟机对JVM规范的实现(1.8以后),使用本地内存作为这些信息的存储空间
12、常量池

 常量池,是Class文件的一部分,可以看做是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型,这部分内容将在类加载后存放到方法区的运行时常量池

 运行时常量池,是方法区的一部分,相对于class文件常量池具有动态性。

13、永久代为什么要被元空间替代

 1)为永久代设置空间大小很难确定,如果动态加载的类过多就会产生OOM。永久代和元空间最大的区别就是:元空间并不在虚拟机中,而是使用本地内存

 2)对永久代进行调优很困难

14、StringTable为什么要调整?

 jdk7将StringTable放到了堆空间中。因为永久代的回收效率很低,在full gc的时候才会出发。而full gc是老年代的空间不足、永久代不足时才会触发。这就导致StringTable回收效率不高。而我们开发中开发中会有大量的字符串被创建,回收效率低,导致永久代内存不足。放到堆中,能及时回收内存。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/572505.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号