`

jvm基础篇

 
阅读更多

(1)内存模型以及分区,需要详细到每个区放什么。

堆:Java虚拟机管理内存中最大的一块,线程共享区域。所有对象实例和数组都在堆上分配内存空间。

栈:线程私有,每个线程都会创建一个虚拟机栈,生命周期与线程相同。每个方法被执行的时候就会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。一个方法执行的过程对应着一个栈帧的入栈到出栈过程。

方法区:用于存储类信息,常量,静态变量等信息,是线程共享区域。

程序计数器:一块较小的内存空间,作用是当前执行字节码的行号指示器。

(2) 堆里面的分区:新生代(Eden,survival)老年代,各自的特点。

堆中存储对象实例,是垃圾回收的主要区域。为了方便垃圾回收,将堆区域分为新生代和老年代两个区域。

新生代:大量对象(98%)都是朝生夕死,因此在进行垃圾回收的时候采用复制算法进行垃圾回收,因为只需付出商量存货对象的复制成本就可以完成收集。但是由于新生代大量对象都是非存活状态,按照常规复制算法1:1划分内存会造成大量空间的浪费。因此新生代又可以划分为一块较大的Eden区域和两块较小的Survivor空间,每次使用Eden和其中一块Survivor区域。回收时,将存活的对象一次性拷贝到另一块Survivor空间上,再清理掉用过的Eden和Survivor空间。默认Eden区域:Survivor区域=8:1 也就是每次使用新生代容量的90%,只有10%被浪费。但是当Survivor区域不足 以存储回收后存活的对象时,需要老年代进行空间担保,这些对象直接通过分配担保机制进入老年代。

老年代:判断对象是否死亡,至少进行两次标记过程。如果对象在Eden出生并且经过一次gc后仍然存活,并且能够被Survivor容纳的话,将会被移动到Survivor区域,并将其年龄设置为1,如果它还能熬过下一次gc收集,年龄再+1.默认情况下当年龄到达15后,就会晋升到老年代中。老年代采用标记清除和标记整理算法进行垃圾收集。

(3)对象创建方法,对象的内存分配,对象的访问定位。

虚拟机遇到一个new指令时,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,需要先执行相应的类加载过程。
对象创建,内存分配详解

对象访问定位符:

1.句柄访问方式:java堆中划分一部分空间作为句柄池,栈reference中存储对象的句柄地址,句柄中包含对象实例数据和各自对象具体地址。即对象实 例数据指针指向堆的实例池对象地址、对象类型数据指针指向方法区的对象类型数据。

优势:reference中存在稳定的句柄地址。对象被移动时只改变句柄中实例数据指针。

2.直接指针访问方式: reference中直接存储对象实例地址,对象实例数据中有一小块区域存储对象类型数据指针,同样指向方法区。

优势:节省了一次指针定位的开销,访问速度更快。

(4)GC的两种判定方法:引用计数与引用链

1.引用计数:给对象添加一个引用计数器,每当有一个地方引用它时,计数器加1。引用失效时,计数器减1 。当计数器为0时,对象就不可能再被使用。

残留问题:循环引用

2.引用链(可达性分析算法):通过Gc-Root的对象为起点,通过这个节点向下搜索,搜索所走过的路径为引用链。当一个对象到Gc-Root没有任何引用链连接时,证明对象不可用。

可作为Gc-Root的对象:

虚拟机栈中的引用对象。
本地方法栈中引用的对象。
方法区类静态属性引用的对象。
方法区中常量引用的对象。

(5)GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方。

1.标记清除算法:首先标记处所有需要回收的对象,在标记完成后统一进行回收。

缺点:标记的过程效率不高、标记清除之后产生大量不连续的内存碎片,当需要申请大块连续内存空间时,无法找到。

2.复制算法:将内存按容量费为大小相等的两块区域,每次只使用其中的一块,当一块内存用完了,就将还存活的对象复制到另一块内存上面,然后吧使用过的那块内存统一清理掉。

缺点:每次只能使用总内存容量的一半。在对象存活较多的情况下会进行大量复制操作,效率底下。

3.标记整理算法:和标记清除算法一样,先对死亡对象进行标记,然后将存活对象向一端移动,然后直接清理掉边界以外的内存。

4.分代收集算法:根据对象存活周期的不同,将内存划分为新生代和老年代,新生代使用复制算法,老年代使用标记清除或标记整理算法进行垃圾收集。

(6)GC收集器有哪些?CMS收集器与G1收集器的特点。

1.Serial:一个单线程的收集器,在进行垃圾收集时候,必须暂停其他所有的工作线程直到它收集结束。
特点:CPU利用率最高,停顿时间即用户等待时间比较长。

2.Parallel:采用多线程来通过扫描并压缩
特点:停顿时间短,回收效率高,对吞吐量要求高。

3.CMS收集器:采用“标记-清除”算法实现,使用多线程的算法去扫描堆,对发现未使用的对象进行回收。

4:G1:堆被划分成 许多个连续的区域(region)。采用G1算法进行回收,吸收了CMS收集器特点。
特点:支持很大的堆,高吞吐量、支持多CPU和垃圾回收线程、在主线程暂停的情况下,使用并行收集、在主线程运行的情况下,使用并发收集

(7)Minor GC与Full GC分别在什么时候发生?
Minor GC: 从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC。
特点:当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了。所以分配率越高,越频繁执行 Minor G。内存池被填满的时候,其中的内容全部会被复制,指针会从0开始跟踪空闲内存。Eden 和 Survivor 区进行了标记和复制操作,取代了经典的标记、扫描、压缩、清理操作。所以 Eden 和 Survivor 区不存在内存碎片。写指针总是停留在所使用内存池的顶部。
执行 Minor GC 操作时,不会影响到永久代。从永久代到年轻代的引用被当成 GC roots,从年轻代到永久代的引用在标记阶段被直接忽略掉。
质疑常规的认知,所有的 Minor GC 都会触发“全世界的暂停(stop-the-world)”,停止应用程序的线程。对于大部分应用程序,停顿导致的延迟都是可以忽略不计的。其中的真相就 是,大部分 Eden 区中的对象都能被认为是垃圾,永远也不会被复制到 Survivor 区或者老年代空间。如果正好相反,Eden 区大部分新生对象不符合 GC 条件,Minor GC 执行时暂停的时间将会长很多。

Major GC:清理永久代

Full GC:清理整个堆空间—包括年轻代和永久代

Major GC / Full GC:老年代 GC(Major GC / Full GC):指发生在老年代的 GC,出现了 Major GC,经常会伴随至少一次的 Minor GC(但非绝对的,在 ParallelScavenge 收集器的收集策略里就有直接进行 Major GC 的策略选择过程) 。MajorGC 的速度一般会比 Minor GC 慢 10倍以上。

(8) 双亲委派模型:Bootstrap ClassLoader、Extension ClassLoader、ApplicationClassLoader。
JDK 默认提供了如下几种ClassLoader
1. Bootstrp loader
Bootstrp加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib,-Xbootclasspath参数指定的路径以及%JAVA_HOME%/jre/classes中的类。
1. ExtClassLoader
Bootstrp loader加载ExtClassLoader,并且将ExtClassLoader的父加载器设置为Bootstrploader.ExtClassLoader是用Java写的,具体来说就是 sun.misc.LauncherExtClassLoader,ExtClassLoader主要加载2.AppClassLoaderBootstrploader加载完ExtClassLoader后,就会加载AppClassLoader,并且将AppClassLoader的父加载器指定为ExtClassLoader。AppClassLoader也是用Java写成的,它的实现类是sun.misc.Launcher  AppClassLoader,另外我们知道ClassLoader中有个getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要负责加载classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器。
综上所述,它们之间的关系可以通过下图形象的描述:
双亲委托模型
Java中ClassLoader的加载采用了双亲委托机制,采用双亲委托机制加载类的时候采用如下的几个步骤:
1. 当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。
每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等下次加载的时候就可以直接返回了。
2. 当前classLoader的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,一直到bootstrp ClassLoader.
3. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。
说到这里大家可能会想,Java为什么要采用这样的委托机制?理解这个问题,我们引入另外一个关于Classloader的概念“命名空间”, 它是指要确定某一个类,需要类的全限定名以及加载此类的ClassLoader来共同确定。也就是说即使两个类的全限定名是相同的,但是因为不同的ClassLoader加载了此类,
那么在JVM中它是不同的类。明白了命名空间以后,我们再来看看委托模型。采用了委托模型以后加大了不同的 ClassLoader的交互能力,比如上面说的,我们JDK本生提供的类库,比如hashmap,linkedlist等等,这些类由bootstrp 类加载器加载了以后,无论你程序中有多少个类加载器,那么这些类其实都是可以共享的,这样就避免了不同的类加载器加载了同样名字的不同类以后造成混乱。
如何自定义ClassLoader
Java除了上面所说的默认提供的classloader以外,它还容许应用程序可以自定义classloader,那么要想自定义classloader我们需要通过继承java.lang.ClassLoader来实现,接下来我们就来看看再自定义Classloader的时候,我们需要注意的几个重要的方法:
1.loadClass 方法

 

loadClass method declare
public Class<?> loadClass(String name)  throws ClassNotFoundException

 上面是loadClass方法的原型声明,上面所说的双亲委托机制的实现其实就实在此方法中实现的。下面我们就来看看此方法的代码来看看它到底如何实现双亲委托的。

 

loadClass method implement
public Class<?> loadClass(String name) throws ClassNotFoundException
 {  
return loadClass(name, false);
}

 从上面可以看出loadClass方法调用了loadcClass(name,false)方法,那么接下来我们再来看看另外一个loadClass方法的实现。

Class loadClass(String name, boolean resolve)

protected synchronized Class<?> loadClass(String name, boolean resolve) 
 throws ClassNotFoundException   
 {  // First, check if the class has already been loaded  Class c = findLoadedClass(name);
//检查class是否已经被加载过了  if (c == null)
 {     
 try {      
if (parent != null) {         
 c = parent.loadClass(name, false); //如果没有被加载,且指定了父类加载器,则委托父加载器加载。    
  } else {        
  c = findBootstrapClass0(name);//如果没有父类加载器,则委托bootstrap加载器加载      } 
     } catch (ClassNotFoundException e) {         
 // If still not found, then invoke findClass in order          
// to find the class.         
 c = findClass(name);//如果父类加载没有加载到,则通过自己的findClass来加载。      } 
 } 
 if (resolve) 
{     
 resolveClass(c); 
 }  
return c;
}

 

 

分享到:
评论

相关推荐

    JAVA面试汇总(精选系列).rar

    1、基础篇 2、JVM篇 3、多线程&并发篇 4、Spring篇 5、MyBatis篇 6、SpringBoot篇 7、MySQL篇 8、Redis篇 9、SpringCloud篇 10、Nginx篇 11、zookeeper篇 12、kafka篇 13、MQ篇 14、Elasticsearch篇 15、Linux篇 16...

    jvm-readings:JVM读数

    JVM阅读工作正在进行中对于理解... 安全点 本征 Java内存模型JMM基础知识:访问原子性,单词撕裂,顺序一致性,同步顺序,SO-PO / SO一致性,按顺序同步,发生之前,顺序一致性-数据竞速免费,“蟑螂汽车旅馆”,凭空而

    java基础篇——java的起源与演变

    Java 的跨平台原理: Java 源代码---编译---&gt;java 字节码(可跨平台) ---运行---&gt;JVM(java 虚拟机)→Windows,Linux 等平台。JVM 屏蔽了底层运行平台的差别,实现了“以此编译,随处运行”。 垃圾回收器: 不...

    java 基础篇.docx

    自学java总结出来的第一部分知识点,从继承多态到JVM都有详细的介绍,以及里面还有我自己的学习心得,希望对于和我一样自学的小哥哥小姐姐有所帮助。

    Java 面试题之基础篇.zip

    【一线互联网大厂Java核心面试题库】Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等..

    280多页超详细的JAVA核心知识点整理 包含了JVM、java集合、多线程并发、java基础、spring生态原理、微服务等等

    包含了JVM、java集合、多线程并发、java基础、spring生态原理、微服务、设计模式、NETTY与RPC、网络、日志、ZOOKEEPER、KAFKA、RABBITMQ、HBASE、MONGDB、CASSANDRA、负载均衡、数据库、一致性算法、java算法、数据...

    java知识梳理.docx

    基础篇 JVM篇 多线程&并发篇 Spring篇 Mybatis篇 SpringBoot篇 Mysql篇 SpringCloud篇 Dubbo篇 Ngnix篇 MQ篇 数据结构算法篇 Linux篇 Zookeeper篇 Redis篇 分布式篇 网络篇 设计模式 maven篇 ElasticSearch篇 ...

    Java+八股文面经宝典+资源合集

    java面试宝典 ...基础篇、JVM篇、多线程&并发篇、Spring篇、Mybatis、SpringBoot、mysql、SpringCloud、Dubbo、Nginx、MQ、算法、Linux、ZK、Redis、分布式、网络、应试技巧等等;Java程序员必备知识图谱。

    2022最新Java面试题、八股文大全

    基础篇、JVM篇、多线程&并发篇、Spring篇、Mybatis、SpringBoot、mysql、SpringCloud、Dubbo、Nginx、MQ、算法、Linux、ZK、Redis、分布式、网络、应试技巧等等; Java程序员必备知识图谱,一起学起来,卷起来;

    2022Java面试题以及直通大厂八股文大全

    基础篇、JVM篇、多线程&并发篇、Spring篇、Mybatis、SpringBoot、mysql、SpringCloud、Dubbo、Nginx、MQ、算法、Linux、ZK、Redis、分布式、网络、应试技巧等等; Java程序员必备知识图谱,一起学起来,卷起来;

    Java最新2022版面试题及解答(266页)

    基础篇 JVM篇 多线程&并发篇 Spring篇 MyBatis篇 SpringBoot篇 MySQL篇 SpringCloud篇 Dubbo篇 Nginx篇 MQ篇 数据结构与算法 Linux篇 Zookeeper篇 Redis篇 分布式锁 网络篇 设计模式 maven篇 ElasticSearch篇 tomcat...

    BAT大厂2023年Java架构师岗面试题(综合版)

    基础篇 (45道高级面试题) JVM篇 (33道高级面试题) 高并发编程篇 (46道高级面试题) Spring篇(53道高级面试题) MyBatis篇 (34道高级面试题) SpringBoot篇(38道高级面试题) MySQL(34道高级面试题) SpringCloud篇 (68道...

    JVM自动内存管理机制

    Java自动内存管理机制包含两部分:内存分配和内存回收,要想理解内存分配和回收的机制,则需要了解下Java内存区域(Java运行时数据区),这篇随笔将按照下面的线索进行逐步解析:1.Java运行时数据区2.对象“已死”的...

    java面试问题.rar

    1.基础篇 2.JVM篇 3.多线程&并发篇 4.Spring篇 5.MyBatis篇 6.SpringBoot篇 7.MySQL篇 8.Redis篇 9.SpringCloud篇 10.Nginx篇 11.zookeeper篇 12.kafka篇 13.MQ篇 14.Elasticsearch篇 15.Linux篇 16.数据结构与算法...

    程序员们疯传的阿里P8呕心沥血总结:10万字JAVA面试总结分享《10万字总结.pdf》

    里面总共含了基础篇、JVM 篇、多线程 &并发篇、Spring 篇、MyBatis 篇、Spring Boot 篇、MySQL 篇、Redis 篇、Spring Cloud 篇、Nginx 篇、MQ 篇、数据结构与算法篇、Linux 篇、简历篇 14 个技术栈

    2023java最新面试资料汇总

    基础篇 阿里内部资料 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) 3、与平台无关性(JVM是Java跨平台使用的根本) 4、可靠安全 5、支持多线程 ...

    java8源码-interview:常见的面试题整理

    java基础 java集合 java多线程 JVM SDN篇 网络篇 数据库篇 SQL NoSQL javaweb篇 框架篇 Spring框架 SpringMVC框架 数据结构与算法篇 Linux篇 前端篇 java设计模式篇 java高级篇 JUC java8 NIO 高并发下的数据处理与...

    高级java笔试题-JavaInterview:Java面试整理,涵盖基础、JVM、线程并发、框架、MySQL、微服务、Redis、中间件、数

    基础篇 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) 3、与平台无关性(JVM是Java跨平台使用的根本) 4、可靠安全 5、支持多线程 2、面向对象...

    java后端学习推荐书籍清单

    《鸟哥的Linux私房菜基础篇第三版》 《深入浅出Spring Boot2》《图解Java多线程设计模式》 《深入理解Java虚拟机:JVM高级特性与最佳实践》 《深入理解计算机系统(原书第三版》《Netty权威指南 第2版》 《Netty 4...

Global site tag (gtag.js) - Google Analytics