快速认识Java内存区域划分

Java内存区域.jpg

Java 内存区域中比较重要也是经常被提到的几部分是:程序计数器,栈(Stack),堆(Heap)方法区,它们都定义在被称作运行时数据区(Runing Data Area)的区域中。

其中程序计数器栈(Stack)是随线程启动而生,线程结束而灭的,也就属于线程私有。而堆(Heap)方法区是由JVM启动时创建切被所有线程共享的。

程序计数器

我们知道所有程序代码在最底层都是要被转化为机器指令才能够被电脑识别并执行。当前程序不在是执行1+1或简单的打印字符串(实际上执行打印字符串相对于1+1已经是比较复杂的功能了,包含多个指令),而是要完成更加复杂的功能时,其所包含的指令也就更多,那么为了按逻辑顺序执行这些指令,就需要一个计数器来帮助一条条提取指令或指出下一条指令的位置。这里说的是CPU中的程序计数器的概念,换成JVM 程序计数器,其所承担的任务是基本一样的,只需要将指令换成字节码行号即可。
JVM的字节码解释器通过改变程序计数器的当前值,来提取下一条需要执行字节码的行号(既被编译为二进制的java代码)。所有的完成分支,循环,跳转,异常处理,线程恢复等的功能都是依赖它来完成的。

另外,由于Java的多线程特性(通过轮流切换并分配CPU的使用权,CPU在同一时间也只会执行一个线程中指令),为了在线程切换后能够恢复到正确位置,所以每个线程都有自己的独立的 程序计数器,这就是所谓的线程私有。

栈(Stack)

需要特别指出的是,这里说的栈(Stack)是指虚拟机栈 (在jvm规范中,栈分为虚拟机栈也就是执行Java 方法时用到的,还有本地方法栈,两者区别在与本地方法栈为执行Native方法服务,Sun公司的jvm 称为HotSpot,它将虚拟机栈本地方法栈合二唯一了)。
相比程序计数器,栈(Stack)的出镜率更高,也离开发人员更近。在栈(Stack)中包含了用于Java方法执行时所需要的局部变量表,操作数,动态链接以及方法出口等信息。由于操作数,我们常说的栈其实只是其中的局部变量表(至少我这个级别的coder是这样),这主要是因为操作数,动态链接以及方法出口等与我们关系并不大,这也就造成了局部变量表成为栈(Stack)的代名词。

之所以局部变量表被我们常常提到,是因为他的作用。局部变量表是用于存放编译期间就已知的基本数据类型以及对象引用(地址指针或对象句柄)。

public void example(){
      int a=1; 
      User user=new User();
}

以上代码中的 int a 与 User user 都是存放在局部变量表中。其中a是基本数据类型,它指向了一个值为1的内存空间,该内存空间的大小有类型int限定。user则存放的是new User() 这个对象在堆(Heap)中的内存位置。另外,以上代码之所以要声明一个方法体,是为了强调局部变量概念,如果ause是全局变量,那么它们则在堆内存中属于对象,而如果他们是加上关键static的静态变量或者加上final的常量,则会在方法区常量池中属于类。
栈是线程私有的,随线程结束而空间被回收。栈的大小是有限制的,当出现线程请求深度大于栈的最大深度则会出现StackOverFlow异常;而当Stack需要动态扩展而内存没有足够空间时则会出现OutOfMemoryError异常。

堆(Heap)

的唯一作用就是存放所有对象实例与数组的。它是线程共享的,是Jvm所有管理的内存中最大的一块,也是垃圾收集器GC管理的主要区域。
为了GC更好的进行内存回收,大部分GC使用了分代收集算法,它将堆划分了新生代与老年代。其中新生代又被划分为Eden空间、From Survivor空间和To Survivor空间(Eden是伊甸园,Survivor是幸存者,新创建的对象会优先在Eden中,当第一次GC清理时未被清理的对象则会移动到Survivor空间。这部分会在将来讨论GC时细说)。
的空间大小也是有限制的。我们可以通过参数-Xmx与-Xms来制定最大与最小空间。当超出-Xmx所设置的量时,则出现OutOfMemoryError:heapSpace 异常;

方法区

方法区用于存储虚拟机启动时加载的类信息,常量和静态变量。与堆一样,方法区也是线程共享的。与其他版本的JVM不同,SUN 公司的Hotspot 虚拟机将方法区划分为永久代(Permanent Generation)*。

大多数JAVA开发人员,尤其是会使用很多三方JAR的WEB开发人员都应该见过OutOfMemoryError:PermGen space 这个异常信息。出现原因便是方法区发生了内存溢出。虽然GC在方法区也会进行回收,但其目的是卸载类和回收常量池,大部分情况下,回收效果都不是很好。方法区的溢出在使用如Spring或Hibernate(这些框架会在运行时通过CGLib字节码技术来增强原有类),或者有大量JSP文件,又或者OSGI等会有大量动态生成的类被加载到方法区的应用中更容易出现。 在不能精简加载的jar和应用本身包含的类或常量,静态变量的情况下,可通过参数-XX:PermSize和-XX:MaxPermSize参数来设置方法区大小,来减少OutOfMemoryError:PermGen space异常的出现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容