jvm-内存区域

jvm-内存区域

      • jvm内存区域图:
      • 程序计数器
      • java虚拟机栈
      • 本地方法栈:
      • java堆
      • 方法区
      • 直接内存

jvm内存区域图:

jvm-内存区域_第1张图片

程序计数器

特点:

  • 较小的内存空间
  • 当前线程所执行的字节码的行号指示器,用于选取下一条需要执行的字节码指令。分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。
  • 线程私有
  • 没有规定任何OutOfMemoryError情况的内存区域

案例:

jvm-内存区域_第2张图片
jvm-内存区域_第3张图片
iconst:将常量值进栈

istore: 将一个数值从操作数栈存储到局部变量表

iload:压入操作数栈

bipush:将int ,float,String常量值推送到栈顶

iadd : 加

imul :乘

goto:跳转

if_icmpne:比较栈顶两int型数值大小,当结果不等于0时跳转

详情请看:

https://blog.csdn.net/zhangpan19910604/article/details/52254053

https://docs.oracle.com/javase/specs/jvms/se8/html/index.html

java虚拟机栈

特点:

  • 线程私有
  • java方法执行的时候,会创建一个栈帧
  • 异常:StackOverflowError,OutOfMemoryError

栈帧:

  • 局部变量表
    • 基本数据类型
    • 对象引用
    • returnAddress
    • long,double会占用亮哥局部变量空间(slot)
  • 操作数栈
  • 动态链接
  • 方法出口

StackOverFlowDemo:

/**
 * VM Args: -Xss128k
 * test stack over flow
 * @author shawn
 */
public class StackOverFlowDemo {

   private int stackLength = 1;

   public void recursion(){
      stackLength ++;
      recursion();
   }

   public static void main(String[] args) {
      StackOverFlowDemo demo = new StackOverFlowDemo();
      try {
         demo.recursion();
      } catch (Throwable e) {
         System.out.println("current stack depth: " + demo.stackLength);
         throw e;
      }
   }

}
/*
output:
current stack depth: 982
Exception in thread "main" java.lang.StackOverflowError
	at com.shawn.jvm.StackOverFlowDemo.recursion(StackOverFlowDemo.java:13)
	at com.shawn.jvm.StackOverFlowDemo.recursion(StackOverFlowDemo.java:14)
	at com.shawn.jvm.StackOverFlowDemo.recursion(StackOverFlowDemo.java:14)
	at com.shawn.jvm.StackOverFlowDemo.recursion(StackOverFlowDemo.java:14)
*/

OutOfMemoryDemo:

		while(true){
			new Thread(()->{
					while(true){
						
					}
			}).start();
		}

运行结果:

unable to create new native thread

本地方法栈:

与虚拟机栈非常相似,区别不过就是虚拟机栈执行的是java方法,而本地方法栈则是执行的native方法。

java堆

特点:

  • 线程共享
  • 存放的是对象实例以及数组
  • GC主要区域
  • 三个部分:
    • 新生区
    • 养老区
    • 永久区

逻辑上有三个部分:新生区(young),养老区(Old Tenure),永久区(Perm)java8以后称永久区为元空间

物理上只有两个部分:新生区(young),养老区(Old Tenure),元空间在本地内存中,不在JVM中!

GC的主要区域是young,old。

具体放到垃圾回收那一部分来说明

案例

/**
 * VM -Args -Xms6m -Xmx6m -XX:+HeapDumpOnOutOfMemoryError
 * @author shawn
 */
public class HeapDemo {

   public static void main(String[] args) {
      List<Object> list = new ArrayList<>();
      int i = 0;
      try {
         while (true){
            byte[] bytes = new byte[1024];
            list.add(bytes);
            i++;
         }
      } catch (Throwable e) {
         long maxMemory = Runtime.getRuntime().maxMemory();
         long totalMemory = Runtime.getRuntime().totalMemory();
         System.out.println("i = " + i);
         System.out.println("maxMemory = " + maxMemory);
         System.out.println("totalMemory = " + totalMemory);
         throw e;
      }


   }

}
/*
output:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid19760.hprof ...
Heap dump file created [6065661 bytes in 0.027 secs]
i = 4440
maxMemory = 5767168
totalMemory = 5767168
Exception in thread "main" Exception in thread "Monitor Ctrl-Break" java.lang.OutOfMemoryError: Java heap space
	at com.shawn.jvm.HeapDemo.main(HeapDemo.java:17)
*/

方法区

特点:

  • 线程共享
  • 存储类信息,常量,静态变量,即时编译器后的代码
  • 运行时常量池,用于存放各种字面量和符号引用
// -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
public class OomDemo {
    
    static class OOMTest{}

    public static void main(String[] args) throws Throwable {

        int i = 0; // 模拟计数器

        try {
            while (true){
                i++;
                // 不断的加载对象! Spring的 cglib;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOMTest.class);
                enhancer.setUseCache(false);
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return method.invoke(o,args);
                    }
                });
                enhancer.create();
            }
        } catch (Throwable e) {
            System.out.println("i=>"+i);
            e.printStackTrace();
        }
        
    }
}

直接内存

/**
 * -Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
 * @author shawn
 */
public class DirectBufferDemo {

	public static void main(String[] args) throws Throwable {
		System.out.println("配置的MaxDirectMemorySize"
			+ VM.maxDirectMemory()/(double)1024/1024+"MB");

		TimeUnit.SECONDS.sleep(2);

		// ByteBuffer.allocate(); 分配JVM的堆内存,属于GC管辖
		// ByteBuffer.allocateDirect() ; // 分配本地OS内存,不属于GC管辖
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
		// java.lang.OutOfMemoryError: Direct buffer memory
	}

}
/*
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
	at java.nio.Bits.reserveMemory(Bits.java:694)
	at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)
	at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
	at com.shawn.jvm.DirectBufferDemo.main(DirectBufferDemo.java:22)
*/

你可能感兴趣的:(java,jvm,jvm,java,内存结构)