• 内存区域与内存溢出异常


    第二章 内存区域与内存溢出异常

    2.2 运行时数据区域

    2.2.1 程序计数器

        程序计数器是当前程序执行的字节码的行号指示器,通过改变程序计数器的值可以实现	              分支,跳转,循环,异常,线程回复等功能
    
       ### 2.2.2 Java虚拟机栈和本地方法栈
    
          线程私有,与线程的生命周期相同。方法执行时在此处创建栈帧用于储存局部变量表,操作数栈,动态链接,方法出口的那个信息。
    

    2.2.3本地方法栈

    	也是线程私有,与线程生命周期相同。它为执行本地方法提供服务
    

    2.2.4 java堆

    	被所有线程共有,可以分为Eden ,From Survivor ,To Survivor .创建对象时在堆上分配内存,也是垃圾收集器管理的主要区域。
    

    2.2.5方法区

    	所有线程共享,用于储存虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在HotSpot中也被称为永久代
    

    2.2.6运行时常量池

    	它是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。运行期可以使用String.intern()方法使字符进入常量池
    

    2.2.7直接内存

    	我觉得就是本机内存,没有什么特别的。
    

    2.3对象

    2.3.1对象的创建

    	先检查这个指令的参数是否能在常量池中定位到类的符号引用,并且检查符号引用的类是否被加载,解析,初始化,如果没有就去加载。然后分配内存,初始化为0值,设置元数据信息,对象的hash码,GC分代年龄,。
    

    2.4实战

    2.4.1 java 堆溢出

    package memoryTest;
    
    
    /**
     * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
     * @author 洪buff
     */
    import java.util.ArrayList;
    import java.util.List;
    
    public class HeapMain {
    	static class OOMObject{
    		
    	}
    	
    	public static void main(String[] args){
    		List<OOMObject> list=new ArrayList<OOMObject>();
    		while(true){
    			list.add(new OOMObject());
    		}
    	}
    
    }
    

    2.4.2本地方法栈和虚拟机栈溢出

    package memoryTest;
    
    /**
     * VM Args: -Xss128K
     * @author 洪buff
     *
     */
    public class JavaVMStackSOF {
    	private int stackLength=1;
    	public void stackLeak(){
    		stackLength++;
    		stackLeak();
    	}
    	
    	public static void main(String[] args)throws Throwable{
    		JavaVMStackSOF oom=new JavaVMStackSOF();
    		try{
    			oom.stackLeak();;
    			
    		}catch (Throwable e) {
    			System.out.println("stack length:"+oom.stackLength);
    			throw e;
    		}
    	}
    
    }
    
    
    
    
    ### 2.4.3本地方法栈溢出
    
    package memoryTest;
    
    /**
     * VM Args:-Xss2M(或者更大)
     * @author 洪buff
     *
     */
    public class JavaVMStackOOM {
    	private void dontStop(){
    		while(true){
    			
    		}
    	}
    	
    	public void stackLeakByThread() {
    		while (true){
    			Thread thread =new Thread(new Runnable(){
    
    				@Override
    				public void run() {
    					dontStop();
    					
    				}
    				
    			});
    			thread.start();
    		}
    		
    	}
    	
    	public static void  main(String[] args) {
    		JavaVMStackOOM oom=new JavaVMStackOOM();
    		oom.stackLeakByThread();
    		
    	}
    	
    
    }
    

    很危险,我不做演示

    2.4.3方法区和运行时常量中intern

    package memoryTest;
    
    public class RuntimeConstanPoolOOM {
    	
    	public static void main(String[] args) {
    		String str1=new StringBuilder("计算机").append("软件").toString();
    		System.out.println(str1.intern()==str1);
    		
    		String str2=new StringBuilder("ja").append("va").toString();
    		System.out.println(str2.intern()==str2);
    	}
    
    }
    

    分析:StringBuilder在堆中创建字符串对象“计算机软件",intern()方法将它的引用复制到了字符串常量池,所以答案是true.

        "java"第一次被创建是在类加载时,在常量池中加载,而str2则是指向堆中的”java"对象,intern()方法返回的时常量池中的“java"所以答案是false.
  • 相关阅读:
    title()、upper()、lower()的用法
    Oracle用户无法访问ASM磁盘组问题
    Oracle-RAC监听服务进程关闭失败问题分析处理
    SHELL-字符串操作和变量替换
    Linux-按文件大小排序
    MySQL-重置root密码问题
    Oracle-表空间添加数据文件扩容出错解决措施
    Logstash-使用
    Logstash-工作原理
    ELK+filebeat+kafka搭建Oracle数据库日志平台
  • 原文地址:https://www.cnblogs.com/c-lover/p/10025541.html
Copyright © 2020-2023  润新知