java 常见问题总结

1.jvm性能优化

--1
-Xmn2048m -XX:+AlwaysPreTouch -Xms4096m -Xmx4096m -XX:-UseBiasedLocking -XX:-UseCounterDecay -XX:AutoBoxCacheMax=20000 -javaagent:/export/Instances/follow.soa/server1/runtime/WEB-INF/cmc-filter-client.jar=/export/Instances/follow.soa/server1/runtime/WEB-INF/lib  -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:MaxTenuringThreshold=6 -XX:+ExplicitGCInvokesConcurrent -XX:ParallelGCThreads=8 -XX:+PerfDisableSharedMem






--2
-Xmn2048m -XX:+AlwaysPreTouch -Xms4096m -Xmx4096m -XX:-UseBiasedLocking -XX:-UseCounterDecay -XX:AutoBoxCacheMax=20000 -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:MaxTenuringThreshold=6 -XX: PermSize=128m -XX:MaxPermSize=512m 
---------
1.-XX:+AlwaysPreTouch 默认用内容最大分页
2.Xmn2048m 新生代
3.Xms4096m 最大jvm内存
4.-XX:-UseBiasedLocking 去掉偏向锁
5.-XX:AutoBoxCacheMax=20000  Interger等缓存数据大小
6.-XX:-UseCounterDecay  (未知)


7.-XX:CMSInitiatingOccupancyFraction


当堆满之后,并行收集器便开始进行垃圾收集,例如,当没有足够的空间来容纳新分配或提升的对象。对于CMS收集器,长时间等待是不可取的,因为在并发垃圾收集期间应用持续在运行(并且分配对象)。因此,为了在应用程序使用完内存之前完成垃圾收集周期,CMS收集器要比并行收集器更先启动。


因为不同的应用会有不同对象分配模式,JVM会收集实际的对象分配(和释放)的运行时数据,并且分析这些数据,来决定什么时候启动一次CMS垃圾收集周期。为了引导这一过程, JVM会在一开始执行CMS周期前作一些线索查找。该线索由 -XX:CMSInitiatingOccupancyFraction=<value>来设置,该值代表老年代堆空间的使用率。比如,value=75意味着第一次CMS垃圾收集会在老年代被占用75%时被触发。通常CMSInitiatingOccupancyFraction的默认值为68(之前很长时间的经历来决定的)。
8.-XX:+UseCMSInitiatingOccupancyOnly
我们用-XX+UseCMSInitiatingOccupancyOnly标志来命令JVM不基于运行时收集的数据来启动CMS垃圾收集周期。而是,当该标志被开启时,JVM通过CMSInitiatingOccupancyFraction的值进行每一次CMS收集,而不仅仅是第一次。然而,请记住大多数情况下,JVM比我们自己能作出更好的垃圾收集决策。因此,只有当我们充足的理由(比如测试)并且对应用程序产生的对象的生命周期有深刻的认知时,才应该使用该标志。
9.-XX:MaxTenuringThreshold=6
这是GC里改动效果最明显的一个参数了。对象在Survivor区熬过多少次Young GC后晋升到年老代,JDK7里看起来默认是6,跑起来好像变成了15。


Young GC是最大的应用停顿来源,而新生代里GC后存活对象的多少又直接影响停顿的时间,所以如果清楚Young GC的执行频率和应用里大部分临时对象的最长生命周期,可以把它设的更短一点,让其实不是临时对象的新生代长期对象赶紧晋升到年老代,别呆着。


用-XX:+PrintTenuringDistribution观察下,如果后面几代都差不多,就可以设小,比如JMeter里是2。而我们的两个系统里一个设了2,一个设了6。
10. -XX:+CMSClassUnloadingEnabled,在CMS中清理永久代中的过期的Class而不等到Full GC,JDK7默认关闭而JDK8打开。看自己情况,比如有没有运行动态语言脚本如Groovy产生大量的临时类。它会增加CMS remark的暂停时间,所以如果新类加载并不频繁,这个参数还是不开的好。


2. 用了CMS,新生代收集默认就是-XX:+UseParNewGC,不用自己设。


3. 并发收集线程数


ParallelGCThreads=8+( Processor - 8 ) ( 5/8 ),
ConcGCThreads = (ParallelGCThreads + 3)/4


比如双CPU,六核,超线程就是24个处理器,小于8个处理器时ParallelGCThreads按处理器数量,大于时按上述公式ParallelGCThreads=18, ConcGCThreads=5。除了一些不在乎停顿时间的后台辅助程序会特意把它减少,平时不建议动。


11.内存大小的设计
1. -Xmx, -Xms, 堆内存大小,2~4G均可,再大了注意GC时间。


2. -Xmn or -XX:NewSize and -XX:MaxNewSize or -XX:NewRatio, JDK默认新生代占堆大小的1/3, 个人喜欢把对半分, 增大新生代的大小,能减少GC的频率(但也会加大每次GC的停顿时间),主要是看老生代里设多少长期对象的话,占2/3太多了。可以用-Xmn 直接赋值(等于-XX:NewSize and -XX:MaxNewSize同值的缩写),或把NewRatio设为1来对半分(但如果想设置新生代比老生代大就只能用-Xmn)。


3. -XX: PermSize=128m -XX:MaxPermSize=512m (JDK7)现在的应用有Hibernate/Spring这些闹腾的家伙AOP之后类都比较多,可以一开始就把初始值从64M设到128M,并设一个更大的Max值以求保险。


4. -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m(JDK8),JDK8的永生代几乎可用完机器的所有内存,同样设一个128M的初始值,512M的最大值保护一下。

2.垃圾回收特点:

 

1.Serial收集器

一个单线程的收集器,在进行垃圾收集时候,必须暂停其他所有的工作线程直到它收集结束。
特点:CPU利用率最高,停顿时间即用户等待时间比较长。
适用场景:小型应用
通过JVM参数-XX:+UseSerialGC可以使用串行垃圾回收器。


2.Parallel收集器

采用多线程来通过扫描并压缩堆
特点:停顿时间短,回收效率高,对吞吐量要求高。
适用场景:大型应用,科学计算,大规模数据采集等。
通过JVM参数 XX:+USeParNewGC 打开并发标记扫描垃圾回收器。


3.CMS收集器

采用“标记-清除”算法实现,使用多线程的算法去扫描堆,对发现未使用的对象进行回收。
(1)初始标记
(2)并发标记
(3)并发预处理
(4)重新标记
(5)并发清除
(6)并发重置
特点:响应时间优先,减少垃圾收集停顿时间
适应场景:服务器、电信领域等。
通过JVM参数 -XX:+UseConcMarkSweepGC设置


4.G1收集器

在G1中,堆被划分成 许多个连续的区域(region)。采用G1算法进行回收,吸收了CMS收集器特点。
特点:支持很大的堆,高吞吐量
  --支持多CPU和垃圾回收线程
  --在主线程暂停的情况下,使用并行收集
  --在主线程运行的情况下,使用并发收集
实时目标:可配置在N毫秒内最多只占用M毫秒的时间进行垃圾回收
通过JVM参数 –XX:+UseG1GC 使用G1垃圾回收器

 

3.spring 加载过程

http://www.cnblogs.com/RunForLove/p/5688731.html

4.spring reactor 学习

http://blog.51cto.com/liukang/2090163

 

 

jvm相关总结

1.jvm其实就是一个进程,java程序是其中的一个线程。

2.jvm做了什么

JMM是一个语言级的内存模型,他屏蔽了底层平台的差异,抽象了一个所有平台表现一致的内存模型————这个模型由线程自己可见的本地内存和所有线程可见的主存构成,本地内存存储了主存中的数据副本,JMM通过控制本地内存和主存之间的交互,来约束对一个共享变量的写何时对其他线程可见,从而保证可见性。对下通过不同平台的JVM来屏蔽差异,对上给程序员提供一个一致的抽象模型,程序员写程序的时候,就不用去了解平台差异简化编程。

之所以有个本地内存,是因为JMM本身抽象的就是不同平台计算机存储系统

栈这个就是当前线程可见,不存在共享不共享的问题,他就一个局部变量表,除非是对共享变量的引用

3.计算机存储系统几乎都分为两个子系统——cache缓存系统和虚拟存储系统,cache缓存系统就对应着本地内存,之所以要分成两个子系统,是因为计算机存储的分层结构,而导致这个分成结构的主要因素是速度、容量和每位价格。

在分层存储当中,上一级存储是下一级的缓存,cache存放的CPU当前或马上就要用到的主存数据,现在计算几乎都是三级缓存,L1D 32K,L1I 32K,L2 3M,L3 8M,

主存也是磁盘的缓存,Linux里面有cache/buffer,就是划出来磁盘文件的缓存,其他地方,也是CPU要用才从磁盘加载到内存,windows也差不多

cache是主存的缓存 

https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/637498/

这篇文章的参考链接,有L1 L2的cache结构,比较直观,可以撸一下

《深入理解计算机系统》里面,有讲计算机存储系统的两个子系统,而且把包含L3缓存的逻辑结构也画出来了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值