| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> JVM内存结构阐述 -> 正文阅读 |
|
[Java知识库]JVM内存结构阐述 |
内存结构程序计数器
栈栈可以说是虚拟机栈中的局部变量表 局部变量表中存放了编译期可知的各种基本数据类型,对象引用(不等于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。
栈的演示 ? 主方法调用method1,method1调用method2 method2栈帧在栈的顶部 method1在栈的中间 主方法在栈的底部 局部变量,参数在method2栈帧内占用内存 方法结束完后一步步从顶至下弹出,占用的内存也会被释放掉 问题辨析
? 三个方法 m1线程安全,m2,m3线程安全需要考虑 m2中StringBuilder作为参数(逃离了方法的作用范围)可能被别的线程访问到,需要改成Stringbuffer才能保证线程安全 m3中把sb返回(逃离了方法的作用范围)可能导致被别的线程访问到 栈内存溢出
线程运行诊断
本地方法栈? java中有时候不能与操作系统直接交互,需要本地方法接口(c,c++编写的)与操作系统更底层的api来实现交互 堆堆:通过new关键字,创建对象都会使用堆内存,是java虚拟机所管理的内存中最大的一块,此内存区域唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,堆是垃圾收集器管理的主要区域
堆内存溢出(java.lang.OutofMemoryError:java heap space) 堆内存诊断(idea Terminal中输入命令)
方法区随着虚拟机启动时创建 方法区与堆一样是各个java虚拟机线程共享的一块区域 它存储了跟类的结构相关的一些信息 类的成员变量,常量,静态变量,方法数据,以及成员方法,构造器方法,特殊方法的代码部分等数据,虽然java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它有一个别名叫做Non-Heap(非堆),目的应该是与java堆区分开来 永久代:hotspot虚拟机1.8以前对方法区的称呼 方法区内存溢出:
? 场景:
运行时常量池? 常量池:就是一张表,虚拟机指令可以根据这张表找到要执行的类名,方法名,参数类型,字面量等信息 运行时常量池:运行时常量池是方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放,并把里面的符号变为真实地址 JDK1.8 StringTable(字符串常量池(运行时常量池的一部分))是存在堆中的 jdk1.6即以下版本 StringTable是在永久代中 最重要一点,StringTable中存储的并不是String类型的对象,储存的而是指向String对象的索引,真实对象还是储存在堆中。 ? s1+s2是变量,在运行中可能引用的值被修改,结果不能确定,所以必须在运行期间动态的用StringBuilder进行字符串拼接,而s5是常量在编译期就已经能确定好,不需要StringBuilder方式拼接 字符串是延迟称为对象的,即执行到哪一行才会在字符串常量池中放入那一行 了解字符串常量池StringTable案例 ? String.intern()是一个Native方法,它的作用:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个对象的String对象,否则将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用 这里一开始将x放入了字符串常量池,然后new了一个s放在了堆中 s.intern将s放入串池,但是串池中已经有了“ab” 则不会放入串池,只会返回串池中的对象 所以s2 == x(true) 因为s2是串池中返回的对象 与常量池中的ab相等,s==x为false 常量池已经有了“ab”所以没把s放入串池中,还是存在堆中 (jdk1.8). ? s2==x(true) s== x(true) 因为s.intern()方法将s放入了字符串常量池(串池中没有“ab”) 如果是jdk1.6是将s拷贝,结果又会不同了,这里就不进行详细阐述了 ? x1 == x2 为false 因为常量池已有cd x2.intern()没有将x2放入常量池成功,x2.intern()的返回对象才会与 x1 相同 StringTable调优调整 -XX:StringTableSize=桶个数 考虑将字符串对象是否入池 如果字符串很多 可考虑入池 直接内存直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存频繁地被使用,而且也可能导致OutOfMemoryError异常出现,所以我们放到这里进行讲解 在JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channle)与缓冲区(Buffer)的的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,避免了在Java堆中和Native堆中来回复制数据 显然,本机直接内存的分配不会受到Java堆大小的限制,但是会受到本机总内存以及处理器寻址空间的限制,服务器管理员在配置虚拟机参数时,会根据实际内存设置 -Xmx等参数信息,但经常忽略直接内存,使得各个内存区域综合大于物理内存限制,从而导致动态扩展时OutOfMemoryError异常。
分配和回收原理:
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 5:15:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |