Java运行内存划分

Java程序内存的划分是交由JVM执行的,而不像C语言那样需要程序员自己买单(C语言需要程序员为每一个new操作去配对delete/free代码),放权给JVM虚拟机处理有利也有弊,好处是不容易出现内存泄漏和内存溢出问题,坏处就是自己的JVM发烂渣了,开辟资源空间不释放,此刻就会出现内存泄漏和内存溢出问题。

  1. 内存溢出:Out Of Memmory,系统已经不能再分配空间了,好比你需要50M的空间,系统就只剩下40M。

  1. 内存泄露:Memmory Leak,开辟了资源空间但用完后忘记释放,内存还在被占用,多次内存泄漏就会导致内存溢出。

java的运行步骤

  .java文件--->编译成.class文件--->类加载器加载JVM

类加载器主要有三种

  1. 引导类加载器:用c++编写的,时jvm自带的加载器,负责java平台核心库,用来装载核心类库。改加载器无法直接获取

  2. 扩张类加载器:负责jre/lib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装入工作库

  3. 系统类加载器:负责java -classpath或-D java.class.path所指定的目录下的类与jar包装入工作,时最常用的加载器

public class Math {
    public static final int initData = 666;
    public static MyLock user = new MyLock();
    public int compute() { // 一个方法对应一块栈帧内存区域
        int a = 1;
        int b = 2;
        int c = (a + b)*10;
        return c;
    }

    public static void main(String[] args) {
        Math math = new Math();
        math.compute();
    }
}

 

JAVA把Class文件加载到内存中,并对数据进行效验,解析和初始化,最终形成JVM可以直接使用的JAVA类型的过程。

分为:

1.加载(先加载类,再加载对象!)

将Class字节码内容加载到内存中,并将这些静态数据换成方法区中运行时的二进制数据结构,在堆中生成一个代表这个类的java.lang.class–对象(反射对象)可以指向方法区的数据,作为方法区类数据的访问入口。

class字节码(一个字节数组)->类加载器->方法区运行时数据->class对象->外部可以通过操作class对象,作为操作类的入口。

2.链接

验证:确保加载的类信息符合JVM规范,考虑安全问题。
准备:正式为类变量,类方法(static)分配内存并设置类变量的初始值,这些内存都在方法区内分配。
解析:虚拟机常量池内符号引用替换为直接引用的过程(每个类都有一个常量池并定位常量地址)。

3.初始化

(1).类初始化是执行类构造器方法(不是对象的构造器)的过程。类构造器方法是由编译器自动收集类中所有类变量的赋值动作和静态语句块的语句合并产生的。
(2) .当初始化一个类的时候,如何父类没有初始化,先初始化父类。


内存划分

栈:每一个线程分配一块栈内存,每一个方法对应一块栈帧内存

堆:存放对象,默认对象分代年龄到达15时将会移到老年区。

  当老年区也存满时,将会促发full gc 会导致 stop the word 线程停止运行,所谓的jvm优化也就是减少full gc的发生。

  当发生minor gc时 一批对象大于survivor区50%将会直接移到老年区。(动态年龄判断机制)

程序计数器:用于记录线程执行的代码行号

本地方法栈:执行本地方法时,分配一块本地方法栈内存,本地方法用native关键字修饰,主要用于调用非java实现的代码。

方法区:存放常量、静态变量、类信息等。

字节码执行引擎:主要用于执行代码。

posted @ 2020-05-23 21:28  南鸽  阅读(212)  评论(0编辑  收藏  举报