关注“Java后端技术全栈”
回复“面试”获取全套面试材料
1.什么是JVM
?
JVM
的全称是 「Java Virtual Machine」,也就是咱们耳熟能详的 Java 虚拟机。它能辨认 .class后缀的文件,并且可能解析它的指令,最终调用操作系统上的函数,实现咱们想要的操作。
C++开发进去的程序,编译成二进制文件后,就能够间接执行了,操作系统是可能辨认的。
然而咱们的Java程序就不一样了,应用javac
命令编译进去的的.class文件之后,操作系统是不能辨认的,须要对应JVM
去做一个转换后,操作系统能力辨认。
2.说说JDK
、JRE
、JVM
的关系?
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文件有哪些形式?
- 从本地文件系统中加载.class文件
- 从jar包中或者war包中加载.class文件
- 通过网络或者从数据库中加载.class文件
- 把一个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
,如tomcat
、jboss
都会依据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
区,S0
和S1
一直对象进行复制。对象存活年龄最大默认是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
「特点」:最短回收进展工夫,
「回收算法」:标记-革除
「回收步骤」:
- 初始标记:标记
GC Roots
间接关联的对象,速度快 - 并发标记:
GC Roots Tracing
过程,耗时长,与用户过程并发工作 - 从新标记:修改并发标记期间用户过程运行而产生变动的标记,坏事比初始标记长,然而远远小于并发标记
- 表发革除:革除标记的对象
「毛病」:对CPU资源十分敏感,CPU少于4个时,CMS岁用户程序的影响可能变得很大,有此虚拟机提供了“增量式并发收集器”;无奈回收浮动垃圾;采纳标记革除算法会产生内存碎片,不过能够通过参数开启内存碎片的合并整顿。
收集过程:
serial old
Serial Old收集器是Serial收集器的老年代版本,也是一个单线程收集器,不同的是采纳"标记-整顿算 法",运行过程和Serial收集器一样。
「实用场景」:JDK1.5
前与Parallel Scanvenge
配合应用,作为CMS
的后备预案;
收集过程:
Parallel old
Parallel Old收集器是Parallel Scavenge收集器的老年代版本,应用多线程和"标记-整顿算法"进行垃圾 回收,吞吐量优先;
「回收算法」:标记-整顿
「实用场景」:为了代替serial old
与Parallel 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 即可保障不对全堆扫面也不会脱漏。
「回收步骤」:
- 初始标记:标记
GC Roots
间接关联的对象 - 并发标记:对堆中对象进行可达性剖析,找出存活对象,耗时长,与用户过程并发工作
- 最终标记:修改并发标记期间用户过程持续运行而产生变动的标记
- 筛选回收:对各个
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、ParNew
、Parallel Scavenge
「老年代收集器」:CMS
、Serial Old、Parallel Old
「整堆收集器」:G1
,ZGC
(因为不涉年代不在图中)
22.如何抉择垃圾收集器?
抉择倡议:
- 如果你的堆大小不是很大(比方
100MB
),抉择串行收集器个别是效率最高的。参数:
-XX:+UseSerialGC
。 - 如果你的利用运行在单核的机器上,或者你的虚拟机核数只有 单核,抉择串行收集器仍然是适合的,这时候启用一些并行收集器没有任何收益。
参数:
-XX:+UseSerialGC
。 - 如果你的利用是“吞吐量”优先的,并且对较长时间的进展没有什么特地的要求。抉择并行收集器是比拟好的。
参数:
-XX:+UseParallelGC
。 - 如果你的利用对响应工夫要求较高,想要较少的进展。甚至 1 秒的进展都会引起大量的申请失败,那么抉择
G1
、ZGC
、CMS
都是正当的。尽管这些收集器的 GC 进展通常都比拟短,但它须要一些额定的资源去解决这些工作,通常吞吐量会低一些。参数:
-XX:+UseConcMarkSweepGC
、-XX:+UseG1GC
、-XX:+UseZGC
等。
从下面这些出发点来看,咱们平时的 Web 服务器,都是对响应性要求十分高的。选择性其实就集中在 CMS
、G1
、ZGC
上。而对于某些定时工作,应用并行收集器,是一个比拟好的抉择。
23.相熟哪些JVM调优参数?
X或者XX结尾的都是非转标准化参数
意思就是说准表化参数不会变,非标准化参数可能在每个JDK
版本中有所变动,然而就目前来看X结尾的非标准化的参数扭转的也是非常少。
格局:-XX:[+-]<name> 示意启用或者禁用name属性。例子:-XX:+UseG1GC(示意启用G1垃圾收集器)
堆设置
-Xms
初始堆大小,ms是memory start的简称 ,等价于-XX:InitialHeapSize
`-Xmx 最大堆大小,mx是memory max的简称 ,等价于参数
-XX:MaxHeapSize`
❝留神:在通常状况下,服务器我的项目在运行过程中,堆空间会一直的膨胀与扩张,势必会造成不必要的零碎压力。所以在生产环境中,
JVM
的Xms
和Xmx
要设置成一样的,可能防止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