java java内存模型型与JVM的java内存模型型是一个意思吗

JAVA内存模型与JVM内存模型的区别

Java内存模型规定所有的变量都是存在主存中,每个线程都有自己的工作内存。线程堆变量的操作都必须在工作内存进行,不能直接堆主存进行操作,并且每个线程不能访问其他线程的工作内存。
Java内存模型的Volatile关键字,原子性、可见性、有序性
虚拟机栈:用来放局部变量、堆区对象的引用和常量池对象的引用;但对象本身不存放在栈中,而是存放在堆(new出来的对象)或者常量池中(对象可能在常量池里)(字符串常量对象存放在常量池中。);

方法区:存放类的信息;此区包含常量池(常量池用来放基本类型常量和字符串类型常量),此部分可以回收;方法区可以放用static修饰的变量,但此部分不能回收,因为方法区也叫持久带,永久带基本不参与垃圾回收;

堆::存放一些new出的对象(包含成员变量),和数组。但发生了就不会保存堆里面了。

java对象创建分为两个过程:声明对象引用和创建对象实体。类信息、对象引用、对象实体均在内存的不同区域。

每一个java应用程序均会唯一的对应一个jvm实例,而这个jvm实例将会完成对象的内存分配、程序运行、垃圾回收等工作。JVM将其内存分为三个区域:方法区、栈区、堆区。

  • 方法区:是jvm在装载类文件时,用于存储类的所有描述信息的,这些信息主要包括,类的基本信息(访问修饰符、类名等)、字段信息(修饰符、类型、字段名)、方法信息(修饰符、返回值类型、方法名、参数列表类型、异常、方法体字节码等)、常量池、静态区、classloader以及class的引用
  • 栈区:存放局部变量,基本数据类型和对象引用类型
  • 堆区:用于存放new产生对象的实体,每一个对象实体均会有自己的内存地址,一旦这个内存地址不被任何栈区对象引用,就会成为垃圾,随时被gc回收

  • 步骤:1、将JVM加载到内存
    2、jvm首先检查public类是否存在,存在就会将它加载到内存方法区中,否则抛出异常,结束进程
    3、对类中静态字段进行初始化(显示初始化就为指定的值,否则为默认值),接着执行静态代码块
    4、在栈中创建局部变量,堆中创建对象实体,为堆对象实体的成员变量(非静态)初始化,对于静态字段只需要从方法区的静态区中引用其值即可,执行构造代码块,接着执行构造函数(当然,调用顺序会一直上溯到Object类,每一个构造方法的第一行为super()语句),最后将对象实体堆地址给栈中引用变量

    要注意的是,实例字段包括自身定义的和从父类继承下来的(即使父类的实例字段被子类覆盖或者被private修饰,都照样为其分配内存)
    C++中的引用和JAVA的引用作对比,其实他们两个只是“名称”一样,本质并没什么关系,C++中的引用只是给现存变量起了一个别名(引用变量只是一个符号引用而已,编译器并不会给引用分配新的内存),而JAVA中的引用变量却是真真正正的变量,具有自己的内存空间,只是不同的引用变量可以“指向”同一个对象而已。因此,如果要拿C++和JAVA引用对象的方式相对比,C++中的指针倒和JAVA中的引用如出一辙,毕竟,JAVA中的引用其实就是对指针的封装

Java内存模型中的三个代

本文介绍Java内存模型中的三个代:年轻代,终身代以及永久代。文中图示了各个代的默认排列。本文适用于JDK 1.4到JDK6。

之前也介绍过,下面主要介绍Java内存模型中的三个代。Java的内存模型由3个代组成,各个代的默认排列有如下图(适用JDK1.4.*  到 JDK6):

Java 的内存模型分为

叫法不同,表达的意思却是基本相同。

注意Young(年轻代)还可以分为Eden区和两个Survivor区(from和to,这两个Survivor区大小严格一至),新的对象实例总是首先放在Eden区,Survivor区作为Eden区和Tenure(终生代)的缓冲,可以向Tenure(终生代)转移活动的对象实例。

Tenure(终生代)中存放生命周期长久的实例对象,但并不是如它的名字那样是终生的,里面的对象照样会被回收掉。

Perm(永久代)则是非堆内存的组成部分。主要存放加载的Class类级对象如class本身,method,field等等。

有同学可能已经注意到了,每个代都有的Virtual区又是什么?

我们知道有一些参数可以影响以上各代的大小。

在JVM启动时,就已经保留了固定的内存空间给Heap内存,这部分内存并不一定都会被JVM使用,但是可以确定的是这部分保留的内存不会被其他进程使用。这部分内存大小由 -Xmx 参数指定。

而另一部分内存在JVM启动时就分配给JVM,作为JVM的初始Heap内存使用。影响这个的参数是 -Xms ,如果 -Xms 指定的值比-Xmx 的小,那么两者的差值就是Virtual内存值。随着程序的运行,Eden区、 Tenured区和Perm区会逐渐使用保留的Virtual空间。


可以看到堆内存默认值最大不会超过1G。

使用堆内存空闲百分比来定义,一般在32位机器上的默认值如下:

当空闲堆内存所占堆内存百分比低于40%,JVM就会试图扩张堆内存空间;当空闲堆内存所占堆内存百分比高于70%,JVM就会试图压缩堆内存空间。

ps:以上默认值在不同平台会有不同的值,如果是64位系统,这些值一般需要扩张30%,来容纳在64位系统下变大的对象。

32位系统下默认值如下:


以上就介绍了Java内存模型的三个代。


我要回帖

更多关于 java内存模型 的文章

 

随机推荐