1、java内存与内存溢出

1.1 JVM分为哪些区,每一个区干嘛的?(见java虚拟机38页)

  • (1)程序计数器(线程私有)
    当前线程执行字节码的信号指示器。(每个线程都会在程序计数器中存储其指令,从而实现线程切换后恢复到正确的执行位置)
  • (2)虚拟机栈(就是常说的栈,线程私有)
    每个方法执行(开始到结束就是这个方法的生命周期)都会创建一个栈帧,栈帧存储局部变量表、操作数栈、动态链接、方法出口等信息。

    1)(栈内存)为虚拟机执行java方法服务:方法被调用时创建栈帧–>局部变量表–>局部变量–>对象引用
    2)如果线程请求的栈深度超出了虚拟机所允许的深度,就会出现StackOverFlowError. -Xss规定了栈的最大空间;
    3)虚拟机栈可以动态扩展,如果扩展到无法申请到足够的内存,会出现OOM(OutOfMemoryError)
      而我们最常用的就是局部变量表,局部变量表包括如下内容:
    1)基本数据类型: boolean byte char short int float long double
    注意基本类型的包装类型:Boolean、Byte、Character、Short、Integer、Float、Long、Double
    2) 对象引用类型:类、接口、数组 (不是对象本身,可能是一个指向对象起始地址的引用指针)
      问题:包装类型是放在栈中么:String Interget(看包装类型是怎么用的:若直接定义则内容在常量池中,若new一个对象则在堆中)

  • (3)本地方法栈 与虚拟机实现的功能非常相似,不同之处在于虚拟机执行java方法(字节码)服务,而本地方法栈执行Native 方法服务(非java方法写的)。

  • (4)java 堆(线程共享) 虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,对象在失去引用,就会被java虚拟机回收.

1)被所有线程共享,在java虚拟机启动时创建,几乎所有的对象实例都存放到堆中;
2)GC管理的主要区域;
3)物理上不连续,逻辑上连续,并可以动态扩展,无法扩展时抛出OutOfMemoryError;

  • (5)方法区(线程共享)(虚拟机把方法区叫做永久代)
    用于存储已被虚拟机加载的类信息、常量、静态变量、即编译器编译后的代码等数据。
  • 注意:特别注意静态变量static修饰的变量在方法区。

1)运行时常量池(是方法区的一部分)
常量不一定只有在编译器产生,在运行期也可以(如String的intern(方法))。

  • (6)直接内存(了解即可)
    不是虚拟机运行时数据区的一部分。是native函数直接分配的堆外内存,这样避免了java堆和native堆来回复制数据。

2、垃圾收集器与内存分配策略

2.1 jvm垃圾处理方法(标记清除、复制、标记整理)

  • 标记—清除算法
  • (1)标记阶段:先通过根节点,标记所有从根节点开始的对象,未被标记的视为垃圾对象;
    (2)清除阶段:清除所有未被标记的对象。
  • 复制算法
    将原有的内存空间分成两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中存活对象复制到未使用的内存块中,然后清除正在使用的内存块中所有对象。
  • 标记—整理算法:(若对象存活率比较高,就要进行多次复制,效率比较低)
    (1)标记阶段:先通过根节点,标记所有从根节点开始的可达对象,未被标记的视为垃圾对象。
    (2)整理阶段:将所有的存活对象压缩到内存的一端(或向一端移动),之后清理边界所有的空间。
  • 分代收集算法 只是根据对象存活周期的不同将内存划分为几块。一般把java堆分为新生代和老年代。
    新生代大量对象死亡,只有少数对象存活,采用复制算法; 老年代对象存活率高,没有额外空间对它进行分配,故采用标记-清除或标记-整理算法。

三种算法的比较:

  • (1)效率:复制算法 > 标记-整理算法 > 标记-清除算法(此处的效率只是简单的对比时间复杂度)
  • (2)内存整理度:复制算法 = 标记-整理算法 》标记-清除算法
  • (3)内存利用率:标记-整理算法 = 标记-清除算法 》复制算法

2.2 JVM如何GC?新生代,老年代,持久代,都存储哪些东西,以及各个区的作用?

内存的分配
1、大多数新生的对象在Eden区分配,当Eden区没有足够空间进行分配时,虚拟机就会进行一次Minor GC.(Survivor是两个)

新生代:
在方法中new一个对象,方法调用完毕后,对象就会被回收,这就是一个典型的新生代对象。(新生对象在eden区经历过一次minorGC并且被Survivor容纳的话,对象年龄为1,每一次熬过MinorGc 年龄就会加1,直到15,就会晋升到老年代)
注意动态对象的判定:Survivor空间中相同年龄的对象大小总和大于Survivo空间的一半,大于或等于该年龄的对象就可以直接进入老年代。
老年代:
(1)在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到老年代中,而且大对象(占用大量连续内存空间的java对象如很长的字符串及数组)直接进入老年代。
(2)当survivor空间不够用时,需要依赖老年代进行分配担保。
永久代:即方法区

2.3 GC引用可达性分析算法中,哪些对象可作为GCRoots对象?

  • (1)java虚拟机栈中的对象(引用对象);
  • (2)方法区中的静态成员;
  • (3)方法区中的常量引用对象;
  • (4)本地方法区中的JNI(Native方法)引用对象 ;

2.4 什么时候进行MinorGC,FullGC

MinorGC(新生代GC)
当Eden区没有足够空间进行分配时,虚拟机就会进行一次Minor GC.
(1)新生代中的垃圾收集动作,采用的是复制算法;
(2)对于较大的对象(很长的字符串、数据、集合),在Minor GC的时候可以直接进入老年代。
FullGC(老年代GC)
(1)Full GC 是发生在老年代的垃圾收集动作,采用的是标记-清除/整理算法;
(2)由于老年代的对象几乎都是在survivor区熬过来的,不会那么容易死掉,因此Full GC发生的次数不会像MInor GC那么频繁,FullGC清理时间是Minor GC的10倍。

2.5 各个垃圾回收器是怎么工作的

Serial收集器

(1)是一个单线程收集器,它“单线程”的意义并不仅仅说明它只会使用一个cpu或一条线程去完成垃圾回收工作。而是在收集垃圾时,暂停其他的工作线程。
(2)新生代采用复制算法,stop-the-world(消除或者减少工作线程因内存回收而导致停顿)。
(3)老年代采用标记–整理算法。
(4)简单高效,client模式下默认的新生代收集器。

ParNew收集器

(1)ParNew收集器是Serial收集器的多线程版本;
(2)新生代采用复制算法,stop-the-world;
(3)老年代采用标记–整理算法;
(4)它是运行在server模式下首选新生代收集器;
(5)除了serial收集器之外,只能它能和cms收集器配合工作。

ParNew Scanvenge收集器

(1)类似ParNew,但是更加关注吞吐量。目标是:达到一个可控制吞吐量的收集器;
(2)停顿时间和吞吐量不可能同时调优。我们一方面希望停顿时间少,另一方面希望吞吐量高,其实这是矛盾的。
因为:在GC的时候,垃圾回收的工作量是不变的,如果停顿时间减少,那频率就会提高;既然频率提高了,说明就会频繁的进行GC,那吞吐量就会减少,性能就会降低。

G1收集器(核心重点)

(1)是当今收集器发展的最前沿成果之一,对垃圾回收进行划分优先级的操作,这种有优先级的区域回收方法保证了它的高效率;
(2)最大的优点是结合了空间整合,不会产生大量的碎片,也降低了进行GC的频率;
(3)让使用者明确指定停顿的时间。

CMS收集器:(Concurrent Mark Sweep:并发标记-清除 老年代收集器)

(1)一种以获得最短回收停顿时间为目标的收集器,适用于互联网网站或者B/S系统的服务器上;
(2)初始化标记(stop-the-world):根可以直接关联到的对象;
(3)并发标记(和用户线程一起):主要标记过程,标记全部对象;
(4)重新标记(stop-the-world):由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正;
(5)并发清除(和用户线程一起):基于标记结果,直接清理对象。
注意:CMS有三个致命的问题:1、cpu资源占用 2、浮动的垃圾无法清除 3、内存碎片

2.6 java有几种引用类型,什么情况下使用软引用,GC时如何判定哪些软引用需要回收

Java有四种引用类型:
强引用:通过new产生的对象都是强引用。
软引用:一些还有用但不是必须的对象可以使用软引用。比如创建一个软引用数组,这个数组存放了100多个学生对象的信息。内存比较空闲的时候这些对象和强引用没有区别,但内存紧张的时候就会被GC回收。(这就是GC的判定条件)
应用软引用的好处:java在内存不足时,程序不会崩溃;
弱引用:描述非必须对象的(比软引用更弱),当gc工作时,无论内存是否紧张都会回收掉;
实现这个的目的某个对象是偶尔使用,并且在使用时随时能获取,又不想影响垃圾的回收,可以考虑应用这个。
虚引用:无法通过虚引用来获取对一个对象的真实引用。唯一的用处:能在对象被GC时收到系统通知,JAVA中用PhantomReference来实现虚引用。

JVM基础——面试、笔试的更多相关文章

  1. JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  2. [转] JAVA多线程和并发基础面试问答

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  3. JAVA多线程和并发基础面试问答

    转载: JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对 ...

  4. 【多线程】JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  5. iOS开发——面试笔试精华(二)

    面试笔试精华(二) 警告:一定要把英文题目过一遍,有些公司的题目故意弄成英文的!!! 1.        Difference between shallow copy and deep copy? ...

  6. Java---常用基础面试知识点

    综合网上的一点资源,给大家整理了一些Java常用的基础面试知识点,希望能帮助到刚开始学习或正在学习的学员. 1.抽象 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方 ...

  7. 《Java程序猿面试笔试宝典》之Java与C/C++有什么异同

    Java与C++都是面向对象语言,都使用了面向对象思想(比如封装.继承.多态等),因为面向对象有很多非常好的特性(继承.组合等),使得二者都有非常好的可重用性. 须要注意的是,二者并不是全然一样,以下 ...

  8. (转)JAVA多线程和并发基础面试问答

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  9. JVM基础系列开篇:为什么要学虚拟机?

    跟许多人一样,我一开始接触 Java 虚拟机只是因为面试需要用到,所以硬着头皮看看.所以很多人对于为什么要学虚拟机这个问题,他们的答案都是:因为面试.但我经过了几年的学习和实战,我发现其实学习虚拟机并 ...

随机推荐

  1. unity中的常遇到的问题

    1.使用unity的MovieTexture播放视频在物体上,对象只能在电脑上 2.移动端播放全屏视频 Handheld.PlayFullScreenMovie(),视频文件必须放置在Streamin ...

  2. Scratch少儿编程系列:(十一)Scratch编程之简单见解

    一.Scratch官网的说明     With Scratch, you can program your own interactive stories, games, and animations ...

  3. python GIL全局解释器锁与互斥锁 目录

    python 并发编程 多线程 GIL全局解释器锁基本概念 python 并发编程 多线程 GIL与Lock python 并发编程 多线程 GIL与多线程

  4. 开发完成的springboot项目扩展 swagger

    第一步:pom.xml 引入 swagger 配置 <swagger.version>2.9.2</swagger.version> <!--swagger start- ...

  5. [javascript基础]constructor与prototype

    最初对js中 object.constructor 的认识: 在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下 ...

  6. 利用Kruskal算法求最小生成树解决聪明的猴子问题 -- 数据结构

    题目:聪明的猴子 链接:https://ac.nowcoder.com/acm/problem/19964 在一个热带雨林中生存着一群猴子,它们以树上的果子为生.昨天下了一场大雨,现在雨过天晴,但整个 ...

  7. MyBatis时间排序问题

    在数据中create_time字段是DateTime类型, 逆向工程后实体类中对应的成员变量类型为Date 时间排序代码为: 测试结果: 时间排序错乱. 解决方法: 1,在数据库创建varchar类型 ...

  8. Python细节(二)小数据池

    3.8小数据池 python是由代码块构成的 代码块,一个模块.一个函数,一个类,一个文件,eval(),exec()执行的时候也是一个代码块 1.内存地址 id() 通过id() 我们可以查看到一个 ...

  9. Spark RDD理解-总结

    1.spark是什么 快速.通用.可扩展的分布式计算引擎. 2. 弹性分布式数据集RDD RDD(Resilient Distributed Dataset),是Spark中最基本的数据抽象结构,表示 ...

  10. [转载]Linux内核编译

    原文地址:https://blog.csdn.net/qq_34247099/article/details/50949720 写在前面的话: 本人大二,东南大学一个软工狗,正在修一门名为<操作 ...