关于java:搞定这24道JVM面试题要价30k都有底气

37次阅读

共计 12271 个字符,预计需要花费 31 分钟才能阅读完成。

关注“Java 后端技术全栈”

回复“面试”获取全套面试材料

1. 什么是JVM?

JVM 的全称是 「Java Virtual Machine」,也就是咱们耳熟能详的 Java 虚拟机。它能辨认 .class 后缀的文件,并且可能解析它的指令,最终调用操作系统上的函数,实现咱们想要的操作。

C++ 开发进去的程序,编译成二进制文件后,就能够间接执行了,操作系统是可能辨认的。

然而咱们的 Java 程序就不一样了,应用 javac 命令编译进去的的.class 文件之后,操作系统是不能辨认的,须要对应 JVM 去做一个转换后,操作系统能力辨认。

2. 说说 JDKJREJVM 的关系?

JDK是 Sun 公司(已被 Oracle 收买)针对 Java 开发员的软件开发工具包。自从 Java 推出以来,JDK曾经成为应用最宽泛的 Java SDK(Software development kit)。

JRE全称 Java Runtime Environment,是运行基于 Java 语言编写的程序所不可短少的运行环境。也是通过它,Java 的开发者才得以将本人开发的程序公布到用户手中,让用户应用。

JVM 就是 Java 虚拟机,它能辨认 .class 后缀的文件,并且可能解析它的指令,最终调用操作系统上的函数,实现咱们想要的操作。

JDK中蕴含 JRE,也包含JDK,而JRE 也包含JDK

范畴关系:JDK>JRE>JVM

3. 获取 class 文件有哪些形式?

  1. 从本地文件系统中加载.class 文件
  2. 从 jar 包中或者 war 包中加载.class 文件
  3. 通过网络或者从数据库中加载.class 文件
  4. 把一个 Java 源文件动静编译,并加载,加载进来后就,零碎为这个.class 文件生成一个对应的 Class 对象。

4. 生成 Class 对象的有哪些形式?

1. 对象获取。调用 person 类的父类办法getClaass();

2. 类名获取。每个类型 (包含根本类型和援用) 都有一个动态属性,class;

3.Class 类的静态方法获取。forName(“ 字符串的类名 ”)写全名,要带包名。(包名. 类名)

5. 类加载器有哪些?

Bootstrap ClassLoader

负责加载 $JAVA_HOME 中 jre/lib/rt.jar 里所有的 class 或 Xbootclassoath 选项指定的 jar 包。由 C ++ 实现,不是 ClassLoader 子类。

Extension ClassLoader

负责加载 Java 平台中扩大性能的一些 jar 包,包含 $JAVA_HOME 中 jre/lib/*.jar-Djava.ext.dirs指定目录下的 jar 包。

App ClassLoader

负责加载 classpath 中指定的 jar 包及 Djava.class.path所指定目录下的类和 jar 包。

Custom ClassLoader

通过 java.lang.ClassLoader 的子类自定义加载 class,属于应用程序依据本身须要自定义的 ClassLoader,如tomcatjboss 都会依据 j2ee 标准自行实现ClassLoader

6. 如何自定义类加载器?

用户依据需要本人定义的。须要继承自ClassLoader,重写办法findClass()

如果想要编写本人的类加载器,只须要两步:

  • 继承 ClassLoader
  • 笼罩 findClass(String className) 办法

**ClassLoader**超类的 loadClass 办法用于将类的加载操作委托给其父类加载器去进行,只有当该类尚未加载并且父类加载器也无奈加载该类时,才调用 findClass 办法。如果要实现该办法,必须做到以下几点:

1. 为来自本地文件系统或者其余起源的类加载其字节码。2. 调用 ClassLoader 超类的 defineClass 办法,向虚拟机提供字节码。

7. 如何设置 Java 虚拟机栈的大小呢?

能够应用虚拟机参数 -Xss 选项来设置线程的最大栈空间,栈的大小间接决定了函数调用的最大可达深度;

-Xss size

8. 办法区、堆、栈之间到底有什么关系?

栈指向堆

如果在栈帧中有一个变量,类型为援用类型,比方

package com.tian.my_code.test;
public class JvmCodeDemo {public  Object testGC(){
        int op1 = 10;
        int op2 = 3;
        Object obj = new Object();
        Object result=obj;
        return result;
    }
}

这时候就是典型的栈中元素 obj 指向堆中的 Object 对象,result 的指向和 obj 的指向为同一个对象。

应用命令

javac -g:vars JvmCodeDemo.java

进行编译,而后再应用

javap -v JvmCodeDemo.class >log.txt

而后关上 log.txt 文件

办法区指向堆

办法区中会寄存动态变量,常量等数据。

如果是上面这种状况,就是典型的办法区中元素指向堆中的对象。【「红线」

堆指向办法区

办法区中会蕴含类的信息,对象保留再堆中,创立一个对象的前提是有对应的类信息,这个类信息就在办法区中。

9.Java 对象内存是如何布局的?

一个 Java 对象在内存中包含 3 个局部:对象头、实例数据和对齐填充。

10. 如何了解 Minor/Major/Full GC?

还可能问你:请说一下 Minor/Major/Full GC 别离发送在哪个区域。

Minor GC:产生在年老代的 GC Major GC:产生在老年代的 GC。Full GC: 新生代 + 老年代,比方 Metaspace 区引起年老代和老年代的回收。

11. 可能触发条件 Full GC 有哪些?

1)调用 System.gc 时,零碎倡议执行 Full GC,然而不必然执行;

2)老年代空间有余;

3)办法去空间有余;

4)通过 Minor GC 后进入老年代的均匀大小 > 老年代的可用内存;

5)由 Eden 区、From Space 区向 To Space 区复制时,对象大小大于 To Space 可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。即老年代无奈寄存下新年代适度到老年代的对象的时候,会触发 Full GC。

12. 为什么须要 Survivor 区?

如果没有 Survivor,Eden 区每进行一次 Minor GC , 并且没有年龄限度的话,存活的对象就会被送到老年代。这样一来,老年代很快被填满, 触发 Major GC(因为 Major GC 个别随同着 Minor GC,也能够看做触发了 Full GC)。老年代的内存空间远大于新生代,进行一次 Full GC 耗费的工夫比 Minor GC 长得多。

执行工夫长有什么害处? 频发的 Full GC 耗费的工夫很长,会影响大型程序的执行和响应速度。

可能你会说,那就对老年代的空间进行减少或者较少咯。

如果减少老年代空间,更多存活对象能力填满老年代。尽管升高 Full GC 频率,然而随着老年代空间加大, 一旦产生 Full GC, 执行所须要的工夫更长。

如果缩小老年代空间,尽管 Full GC 所需工夫缩小,然而老年代很快被存活对象填满,Full GC 频率减少。

所以 Survivor 的存在意义, 就是缩小被送到老年代的对象, 进而缩小 Full GC 的产生,Survivor 的预筛选保障, 只有经验 16 次 Minor GC 还能在新生代中存活的对象, 才会被送到老年代。

13. 为什么须要两个大小一样的 Survivor 区?

最大的益处就是解决了碎片化。

假如当初只有一个 Survivor 区,咱们来模仿一下流程:

刚刚新建的对象在 Eden 中,一旦 Eden 满了,触发一次 Minor GC,Eden 中的存活对象就会被挪动到 Survivor 区。这样持续循 环上来,下一次 Eden 满了的时候,问题来了,此时进行 Minor GC,Eden 和 Survivor 各有一些存活对象, 如果此时把 Eden 区的 存活对象硬放到 Survivor 区,很显著这两局部对象所占有的内存是不间断的,也就导致了内存碎片化。

永远有一个 Survivor space 是空的,另一个非空的 Survivor space 无碎片。

14. 新生代中 Eden:S1:S2 为什么是 8:1:1?

新生代中的可用内存:复制算法用来担保的内存为 9:1,所以只会造成 10% 的空间节约。可用内存中 Eden:S1 区为 8:1 即新生代中Eden:S1:S2 = 8:1:1

这个比例,是由参数 -XX:SurvivorRatio 进行配置的(默认为 8)。

15. 如何判断对象已死?

援用计数法

给对象增加一个援用计数器,每当一个中央援用它 object 时技术加 1,援用失去当前就减 1,计数为 0 阐明不再援用

  • 长处:实现简略,断定效率高
  • 毛病:无奈解决对象互相循环援用的问题,对象 A 中援用了对象 B,对象 B 中援用对象 A。

public class A {public B b;}
public class B {public C c;}
public class C {public A a;}
public class Test{private void test(){A a = new A();
        B b = new B();
        C c = new C();
        
        a.b=b;
        b.c=c;
        c.a=a;
    }
}

可达性剖析算法

当一个对象到 GC Roots 没有援用链相连,即就是 GC Roots 到这个对象不可达时,证实对象不可用。

GC Roots品种:

Java 线程中,以后所有正在被调用的办法的援用类型参数、局部变量、长期值等。也就是与咱们栈帧相干的各种援用。所有以后被加载的 Java 类。Java 类的援用类型动态变量。运行时常量池里的援用类型常量(String 或 Class 类型)。JVM 外部数据结构的一些援用,比方 sun.jvm.hotspot.memory.Universe 类。用于同步的监控对象,比方调用了对象的 wait() 办法。

public class Test{private void test(C c){A a = new A();
        B b = new B();
        a.b=b;
        // 这里的 a /b/ c 都是 GC Root;}
}

16. 对象的有几种援用类型?

  • 强援用:User user=new User();咱们开发中应用最多的对象援用形式。

    特点:咱们平时典型编码 Object obj = new Object() 中的 obj 就是强援用。

    通过关键字 new 创立的对象所关联的援用就是强援用。

    JVM 内存空间有余,JVM宁愿抛出 OutOfMemoryError 运行时谬误(OOM),使程序异样终止,也不会靠随便回收具备强援用的“存活”对象来解决内存不足的问题。

    对于一个一般的对象,如果没有其余的援用关系,只有超过了援用的作用域或者显式地将相应(强)援用赋值为 null,就是能够被垃圾收集的了,具体回收机会还是要看垃圾收集策略。

  • 软援用:SoftReference<Object> object=new SoftReference<Object>(new Object());

    特点:软援用通过 SoftReference 类实现。软援用的生命周期比强援用短一些。只有当 JVM 认为内存不足时,才会去试图回收软援用指向的对象:即 JVM 会确保在抛出 OutOfMemoryError 之前,清理软援用指向的对象。软援用能够和一个援用队列(ReferenceQueue)联结应用,如果软援用所援用的对象被垃圾回收器回收,Java 虚拟机就会把这个软援用退出到与之关联的援用队列中。后续,咱们能够调用 ReferenceQueue 的 poll()办法来查看是否有它所关怀的对象被回收。如果队列为空,将返回一个 null, 否则该办法返回队列中后面的一个 Reference 对象。

    利用场景:软援用通常用来实现内存敏感的缓存。如果还有闲暇内存,就能够临时保留缓存,当内存不足时清理掉,这样就保障了应用缓存的同时,不会耗尽内存

  • 弱援用:WeakReference<Object> object=new WeakReference<Object> (new Object();ThreadLocal中有应用.

    弱援用通过 WeakReference 类实现。弱援用的生命周期比软援用短。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具备弱援用的对象,不论以后内存空间足够与否,都会回收它的内存。因为垃圾回收器是一个优先级很低的线程,因而不肯定会很快回收弱援用的对象。

    弱援用能够和一个援用队列(ReferenceQueue)联结应用,如果弱援用所援用的对象被垃圾回收,Java 虚拟机就会把这个弱援用退出到与之关联的援用队列中。利用场景:弱利用同样可用于内存敏感的缓存。

  • 虚援用:简直没见过应用,ReferenceQueue、PhantomReference

17.finalize 办法有理解吗?

这个办法就有点相似:某个人被判了死刑,然而不肯定会死。

即便在可达性剖析算法中不可达的对象,也并非肯定是“非死不可”的,这时候他们临时处于“缓刑”阶段,真正宣告一个对象死亡至多要经验两个阶段:

1、如果对象在可达性剖析算法中不可达,那么它会被第一次标记并进行一次刷选,刷选的条件是是否须要执行 finalize()办法(当对象没有笼罩 finalize()或者 finalize()办法曾经执行过了(对象的此办法只会执行一次)),虚拟机将这两种状况都会视为没有必要执行)。

2、如果这个对象有必要执行 finalize()办法会将其放入 F -Queue 队列中,稍后 GC 将对 F -Queue 队列进行第二次标记,如果在重写 finalize()办法中将对象本人赋值给某个类变量或者对象的成员变量,那么第二次标记时候就会将它移出“行将回收”的汇合。

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

标记 - 革除算法

第一步:就是找出沉闷的对象。咱们反复强调 GC 过程是逆向的,依据 GC Roots 遍历所有的可达对象,这个过程,就叫作标记。

第二部:除了下面标记进去的对象以外,其余的都分明掉。

  • 毛病:标记和革除效率不高,标记和革除之后会产生大量不间断的内存碎片

复制算法

新生代应用,新生代分中Eden:S0:S1= 8:1:1,其中前面的 1:1 就是用来复制的。

当其中一块内存应用完了,就将还存活的对象复制到另外一块下面,而后把曾经应用过的内存空间一次 革除掉。

个别对象调配都是进入新生代的 eden 区,如果 Minor GC 还存活则进入 S0 区,S0S1 一直对象进行复制。对象存活年龄最大默认是 15,大对象进来可能因为新生代不存在间断空间,所以会间接接入老年代。任何应用都有新生代的 10% 是空着的。

  • 毛病:对象存活率高时,复制效率会较低,节约内存。

标记整顿算法

它的次要思路,就是挪动所有存活的对象,且依照内存地址程序顺次排列,而后将末端内存地址当前的内存全副回收。然而须要留神,这只是一个现实状态。对象的援用关系个别都是非常复杂的,咱们这里不对具体的算法进行形容。咱们只须要理解,从效率上来说,个别整顿算法是要低于复制算法的。这个算法是躲避了内存碎片和内存节约。

让所有存活的对象都向一端挪动,而后间接清理掉端边界以外的内存。

从下面的三个算法来看,其实没有相对最好的回收算法,只有最适宜的算法。

19. 新生代有哪些垃圾收集器?

serial

Serial 收集器是最根本、倒退历史最悠久的收集器,已经(在 JDK1.3.1 之前)是虚拟机新生代收集的惟一抉择。

它是一种单线程收集器,不仅仅意味着它只会应用一个 CPU 或者一条收集线程去实现垃圾收集工作,更重要的是其在进行垃圾收集的时候须要暂停其余线程。

长处:简略高效,领有很高的单线程收集效率 毛病:收集过程须要暂停所有线程 算法:复制算法 利用:Client 模式下的默认新生代收集器

收集过程:

ParNew

能够把这个收集器了解为 Serial 收集器的多线程版本。

长处:在多 CPU 时,比 Serial 效率高。毛病:收集过程暂停所有应用程序线程,单 CPU 时比 Serial 效率差。算法:复制算法 利用:运行在 Server 模式下的虚拟机中首选的新生代收集器

收集过程:

Parallel Scanvenge

Parallel Scavenge 收集器是一个新生代收集器,它也是应用复制算法的收集器,又是并行的多线程收集 器,看上去和 ParNew 一样,然而 Parallel Scanvenge 更关注 零碎的吞吐量 ;

吞吐量 = 运行用户代码的工夫 / (运行用户代码的工夫 + 垃圾收集工夫)

比方虚拟机总共运行了 120 秒,垃圾收集工夫用了 1 秒,吞吐量 =(120-1)/120=99.167%。

若吞吐量越大,意味着垃圾收集的工夫越短,则用户代码能够充分利用 CPU 资源,尽快实现程序的运算工作。

可设置参数:

-XX:MaxGCPauseMillis 管制最大的垃圾收集进展工夫,-XX:GC Time Ratio 间接设置吞吐量的大小。

20. 老年代有哪些垃圾收集器?

CMS=Concurrent Mark Sweep

「特点」:最短回收进展工夫,

「回收算法」:标记 - 革除

「回收步骤」

  1. 初始标记:标记 GC Roots 间接关联的对象,速度快
  2. 并发标记:GC Roots Tracing过程,耗时长,与用户过程并发工作
  3. 从新标记:修改并发标记期间用户过程运行而产生变动的标记,坏事比初始标记长,然而远远小于并发标记
  4. 表发革除:革除标记的对象

「毛病」:对 CPU 资源十分敏感,CPU 少于 4 个时,CMS 岁用户程序的影响可能变得很大,有此虚拟机提供了“增量式并发收集器”;无奈回收浮动垃圾;采纳标记革除算法会产生内存碎片,不过能够通过参数开启内存碎片的合并整顿。

收集过程:

serial old

Serial Old 收集器是 Serial 收集器的老年代版本,也是一个单线程收集器,不同的是采纳 ” 标记 - 整顿算 法 ”,运行过程和 Serial 收集器一样。

「实用场景」JDK1.5前与 Parallel Scanvenge 配合应用,作为 CMS 的后备预案;

收集过程:

Parallel old

Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,应用多线程和 ” 标记 - 整顿算法 ” 进行垃圾 回收,吞吐量优先;

「回收算法」:标记 - 整顿

「实用场景」:为了代替 serial oldParallel Scanvenge配合应用

收集过程:

G1=Garbage first

JDK 9 开始,JVM 的默认垃圾回收器就从 Parallel GC 调整为 G1,并且开始全面破除 CMS

限度或者缩小 GC 进展工夫相比零碎吞吐量而言更加重要,从 PGC 切换至低提早的 G1 可能为大部分用户带来更好的体验。G1 的性能在 JDK 8 以及后续的 release 版本都失去了极大的优化,G1 是一个具备所有 GC 个性的垃圾回收器,因而将 G1 设置为 JVM 默认的 GC。

依据 JEP-291 中的阐明,为了加重 GC 代码的保护累赘以及减速新性能开发,决定在 JDK 9 中废除 CMS GC。

从 Java 9 开始,如果您应用 -XX:+UseConcMarkSweepGC(激活 CMS GC 算法的参数)参数启动应用程序,则会在上面显示正告音讯:

Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.

如果你想晓得以后利用对应的 JVM 版本,你能够应用以下命令进行查问:

G1 将整个 JVM 堆划分成多个大小相等的独立区域 regin,跟踪各个regin 外面的垃圾沉积的价值大小,在后盾保护一个优先列表,每次依据容许的收集工夫,有线回收最大的 regin,芮然还保留有新生代和老年代的概念,但新生代和老年代不在是物理隔离了,他们都是一部分regin 汇合。

内存“化整为零”的思路:在 GC 根节点的枚举范畴汇总退出 remembered set 即可保障不对全堆扫面也不会脱漏。

「回收步骤」

  1. 初始标记:标记 GC Roots 间接关联的对象
  2. 并发标记:对堆中对象进行可达性剖析,找出存活对象,耗时长,与用户过程并发工作
  3. 最终标记:修改并发标记期间用户过程持续运行而产生变动的标记
  4. 筛选回收:对各个 regin 的回收价值进行排序,而后依据冀望的 GC 进展工夫制订回收打算

G1收集器劣势

「并行与并发」G1能充分利用多 CPU、多核环境下的硬件劣势,应用多个 CPU 来缩短 Stop-The-World 进展工夫。局部收集器本来须要进展 Java 线程来执行 GC 动作,G1收集器依然能够通过并发的形式让 Java 程序持续运行。

「分代收集」G1可能单独治理整个 Java 堆,并且采纳不同的形式去解决新创建的对象和曾经存活了一段时间、熬过屡次 GC 的旧对象以获取更好的收集成果。

「空间整合」G1运作期间不会产生空间碎片,收集后能提供规整的可用内存。

「可预测的进展」G1除了谋求低进展外,还能建设可预测的进展工夫模型。能让使用者明确指定在一个长度为 M 毫秒的时间段内,耗费在垃圾收集上的工夫不得超过 N 毫秒。

收集过程:

G1的回收过程次要分为 3 类:

(1)G1“年老代”的垃圾回收,同样叫 Minor G1,这个过程和咱们后面形容的相似,产生机会就是 Eden 区满的时候。

(2)老年代的垃圾收集,严格上来说其实不算是收集,它是一个“并发标记”的过程,顺便清理了一点点对象。

(3)真正的清理,产生在“混合模式”,它不止清理年老代,还会将老年代的一部分区域进行清理。

ZGC

ZGC(Z Garbage Collector)是一款由 Oracle 公司研发的,以低提早为首要指标的一款垃圾收集器。它是基于 「动静 Region」 内存布局,(临时)「不设年龄分代」,应用了 「读屏障」「染色指针」「内存多重映射」等技术来实现 「可并发的标记 - 整顿算法」 的收集器。

JDK 11 新退出,还在试验阶段,次要特点是:「回收 TB 级内存(最大 4T),进展工夫不超过10ms

「长处」:低进展,高吞吐量,ZGC收集过程中额定消耗的内存小

「毛病」:浮动垃圾

目前应用的非常少,真正遍及还是须要写工夫的。

21. 垃圾收集器之间有什么关系?

「新生代收集器」:Serial、ParNewParallel Scavenge

「老年代收集器」CMS、Serial Old、Parallel Old

「整堆收集器」G1ZGC(因为不涉年代不在图中)

22. 如何抉择垃圾收集器?

抉择倡议:

  1. 如果你的堆大小不是很大(比方 100MB),抉择串行收集器个别是效率最高的。

    参数:-XX:+UseSerialGC

  2. 如果你的利用运行在单核的机器上,或者你的虚拟机核数只有 单核,抉择串行收集器仍然是适合的,这时候启用一些并行收集器没有任何收益。

    参数:-XX:+UseSerialGC

  3. 如果你的利用是“吞吐量”优先的,并且对较长时间的进展没有什么特地的要求。抉择并行收集器是比拟好的。

    参数:-XX:+UseParallelGC

  4. 如果你的利用对响应工夫要求较高,想要较少的进展。甚至 1 秒的进展都会引起大量的申请失败,那么抉择 G1ZGCCMS 都是正当的。尽管这些收集器的 GC 进展通常都比拟短,但它须要一些额定的资源去解决这些工作,通常吞吐量会低一些。

    参数:-XX:+UseConcMarkSweepGC-XX:+UseG1GC-XX:+UseZGC 等。

从下面这些出发点来看,咱们平时的 Web 服务器,都是对响应性要求十分高的。选择性其实就集中在 CMSG1ZGC上。而对于某些定时工作,应用并行收集器,是一个比拟好的抉择。

23. 相熟哪些 JVM 调优参数?

X 或者 XX 结尾的都是非转标准化参数

意思就是说准表化参数不会变,非标准化参数可能在每个 JDK 版本中有所变动,然而就目前来看 X 结尾的非标准化的参数扭转的也是非常少。

格局:-XX:[+-]<name> 示意启用或者禁用 name 属性。例子:-XX:+UseG1GC(示意启用 G1 垃圾收集器)

堆设置

-Xms 初始堆大小,ms 是 memory start 的简称,等价于-XX:InitialHeapSize`-Xmx 最大堆大小,mx 是 memory max 的简称,等价于参数-XX:MaxHeapSize`

留神:在通常状况下,服务器我的项目在运行过程中,堆空间会一直的膨胀与扩张,势必会造成不必要的零碎压力。所以在生产环境中,JVMXmsXmx要设置成一样的,可能防止 GC 在调整堆大小带来的不必要的压力。

-XX:NewSize=n 设置年老代大小-XX:NewRatio=n 设置年老代和年轻代的比值。如:-XX:NewRatio=3,示意年老代与年轻代比值为 1:3,年老代占整个年老代年轻代和的 1 /4,默认新生代和老年代的比例 =1:2。-XX:SurvivorRatio=n 年老代中 Eden 区与两个 Survivor 区的比值。留神 Survivor 区有两个,默认是 8,示意

Eden:S0:S1=8:1:1

如:-XX:SurvivorRatio=3,示意Eden:Survivor=3:2,一个 Survivor 区占整个年老代的 1 /5。

-XX:MaxPermSize=n 设置长久代大小

-XX:MetaspaceSize  设置元空间大小

收集器设置

-XX:+UseSerialGC 设置串行收集器-XX:+UseParallelGC 设置并行收集器-XX:+UseParalledlOldGC 设置并行年轻代收集器-XX:+UseConcMarkSweepGC 设置并发收集器

垃圾回收统计信息

-XX:+PrintGC`-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-Xloggc:filenameGC 日志输入到文件里filename,比方:-Xloggc:/gc.log`

并行收集器设置

-XX:ParallelGCThreads=n 设置并行收集器收集时应用的 CPU 数。并行收集线程数。

-XX:MaxGCPauseMillis=n 设置并行收集最大暂停工夫

-XX:GCTimeRatio=n 设置垃圾回收工夫占程序运行工夫的百分比。公式为 1 /(1+n)

-XX:MaxGCPauseMillis=n设置并行收集最大暂停工夫

并发收集器设置

-XX:+CMSIncrementalMode 设置为增量模式。实用于单 CPU 状况。-XX:ParallelGCThreads=n 设置并发收集器年老代收集形式为并行收集时,应用的 CPU 数。并行收集线程数。

其余

-XX:+PrintCommandLineFlags查看以后 JVM 设置过的相干参数

Dump异样快照

-XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath

堆内存呈现 OOM 的概率是所有内存耗尽异样中最高的,出错时的堆内信息对解决问题十分有帮忙,所以给 JVM 设置这个参数 (-XX:+HeapDumpOnOutOfMemoryError),让JVM 遇到 OOM 异样时能输入堆内信息,并通过(-XX:+HeapDumpPath)参数设置堆内存溢出快照输入的文件地址,这对于特地是对相隔数月才呈现的 OOM 异样尤为重要。

-Xms10M -Xmx10M -Xmn2M -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=D:studylog_hprofgc.hprof

-XX:OnOutOfMemoryError

示意产生 OOM 后,运行jconsole.exe 程序。这里能够不必加“”,因为 jconsole.exe 门路 Program Files 含有空格。利用这个参数,咱们能够在零碎 OOM 后,自定义一个脚本,能够用来发送邮件告警信息,能够用来重启零碎等等。

-XX:OnOutOfMemoryError="C:Program FilesJavajdk1.8.0_151binjconsole.exe"

24.8G内存的服务器该如何设置?

java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0

-Xmx3500m 设置 JVM 最大可用内存为 3550M。

-Xms3500m 设置 JVM 促使内存为 3550m。此值能够设置与-Xmx 雷同,以防止每次垃圾回收实现后 JVM 从新分配内存。-Xmn2g 设置年老代大小为2G

整个堆大小 = 年老代大小 + 年轻代大小 + 办法区大小

-Xss128k 设置每个线程的堆栈大小。JDK1.5当前每个线程堆栈大小为 1M,以前每个线程堆栈大小为 256K。更具利用的线程所需内存大小进行调整。在雷同物理内存下,减小这个值能生成更多的线程。然而操作系统对一个过程内的线程数还是有限度的,不能有限生成,经验值在 3000~5000 左右。

-XX:NewRatio=4 设置年老代(包含 Eden 和两个 Survivor 区)与年轻代的比值(除去长久代)。设置为 4,则年老代与年轻代所占比值为 1:4,年老代占整个堆栈的 1 /5。

-XX:SurvivorRatio=4 设置年老代中 Eden 区与 Survivor 区的大小比值。设置为 4,则两个 Survivor 区与一个 Eden 区的比值为 2:4,一个 Survivor 区占整个年老代的 1 /6 -XX:MaxPermSize=16m 设置长久代大小为 16m。

-XX:MaxTenuringThreshold=0 设置垃圾最大年龄。如果设置为 0 的话,则年老代对象不通过 Survivor 区,间接进入年轻代。对于年轻代比拟多的利用,能够提高效率。如果将此值设置为一个较大值,则年老代对象会在 Survivor 区进行屡次复制,这样能够减少对象再年老代的存活工夫,减少在年老代即被回收的概论。

举荐浏览

图解 MyBatis

《大规模分布式存储系统: 原理解析与架构实战》.pdf

正文完
 0