本文共 3220 字,大约阅读时间需要 10 分钟。
Java内存模型:是多线程里面的,jmm与线程可见性有关Java内存结构:是JVM虚拟机存储空间。
Java内存机构分为:方法区、java堆、栈、本地方法栈。方法区(永久区):就是使用static关键字修饰的基本就是存放在方法区内。 一般来说都是存放常量信息,在类加载的时候就会被初始化。 方法区就是全局的。所有线程都会被共享的。 包括静态工厂创建的对象。只要被static修饰的Java堆:创建的对象、new创建的、数组存放在堆内存。 调优策略就是调堆。 堆所有的线程会被共享的。栈:定义基本的局部变量、局部方法、类的方法。 栈代码运行完毕后就会自动释放内存。 栈是每个线程都是私有的。 互不共享,不会产生线程安全问题。本地方法栈:主要是调用C语言的。jni
1、在项目中,少定义static常量。否则垃圾回收机制根本就不会回收。2、调优主要调堆。3、尽量减少垃圾回收机制的次数,因为垃圾回收的时候线程会被卡死,当然时间很短感受不到就是。4、新生代回收次数尽量比老年代多。
垃圾回收机制:不定时的去回收堆内存空间的资源。
什么是堆?new 出来的对象都会存放在堆内存中。堆内存中分配两个区:新生代、老年代。目的就是垃圾回收机制。垃圾回收机制主要是回收新生代里面的对象。新生代又分为:eden区、s0区、s1区。 s0区与s1区大小相等,目的是垃圾回收机制复制算法。新生代:刚创建对象时候先存放在新生代。老年代:如果对象在频繁的使用,对象会放在老年代。在jvm刚创建对象的时候会先放在eden区。垃圾回收机制需要经常区老年代回收垃圾吗?不需要,因为老年代都是频繁使用的对象。回收较少。垃圾回收机制主要回收新生代。如图:
参数配置:-XX:+PrintGC 每次触发GC的时候打印相关日志-XX:+UseSerialGC 串行回收-XX:+PrintGCDetails 更详细的GC日志-Xms 堆初始值-Xmx 堆最大可用值-Xmn 新生代堆最大可用值-XX:SurvivorRatio 永安里设置新生代中eden控件和from/to空间比例。含义:-XX:SurvivorRatio=eden/from=den/to总结:在实际工作的时候,我们可以直接将初始堆大小与最大堆大小配置相等。这样的好处是可以减少程序运行时垃圾回收次数。从而提高效率。
代码:查看堆内存和使用内存
package com.leeue;import java.text.DecimalFormat;/** * * @classDesc: 功能描述:(配置堆内存初始值大小要与堆最大内存值相等。) * @author:李月 * @Version:v1.0 * @createTime:2018年7月31日 下午2:57:53 */public class Demo { public static void main(String[] args) throws InterruptedException { JvmInfo(); byte[] bytes01 = new byte[1*1024*1024]; System.out.println("分配了1M"); Thread.sleep(2000); JvmInfo(); byte[] bytes02 = new byte[4*1024*1024]; System.out.println("分配了4M"); JvmInfo(); } static private String toM(long maxMemory) { float num = (float) maxMemory / (1024 * 1024); DecimalFormat df = new DecimalFormat("0.00");// 格式化小数 String s = df.format(num);// 返回的是String类型 return s; } public static void JvmInfo() { //最大内存配置信息 long maxMemory = Runtime.getRuntime().maxMemory(); System.out.println("最大内存配置:"+maxMemory+","+toM(maxMemory)+"M"); //当前空闲内存 long freeMemory = Runtime.getRuntime().freeMemory(); System.out.println("当前空闲内存:"+freeMemory+","+toM(freeMemory)+"M"); //已使用内存 long totalMemory = Runtime.getRuntime().totalMemory(); System.out.println("已使用内存:"+totalMemory+","+toM(totalMemory)+"M"); }}
-Xms5m -Xmx20m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:+PrintCommandLineFlags
这里配置了初始值是5M 最大值是20M 设置完成后 垃圾回收机制回收了两次
设置完成后
-Xmn 新生代大小,一般设为整个堆的1/3到1/4左右-XX:SurvivorRatio 设置新生代中eden区和from/to空间的比例关系n/1参数: -Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC-XX:SurvivorRatio 设置新生代中eden区和from/to空间的比例关系n/1 如下图
这个参数是配置新生代与老年代的比例关系-Xms20m -Xmx20m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC -XX:NewRatio=2-XX:NewRatio=2 表示新生代与老年代的关系是2:1 新生代占两份
1、设置初始堆大小要与最大堆大小配置相等。
2、设置新生代与老年带回收比例。 JVM参数调优,怎么让垃圾回收机制经常区新生代进行回收? 答:新生代与老年代比例1/3或1/4
堆溢出: 解决方案: -Xms1m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
栈溢出:产生于递归调用,循环遍历是不会出现栈溢出的。但是循环方法里产生递归调用也会发生栈溢出解决方案:设置线程最大调用深度-Xss5m 设置线程最大调用深度。
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxNewSize=512m"