关注“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