理解JVM2 栈内存,方法区,堆内存
堆,方法区,栈的关系
分配最大堆内存-Xmx32m
class SimpleHeap(val id: Int){
fun show() = println("My id is $id")
}
fun main(args: Array<String>) {
val s1 = SimpleHeap(1)
val s2 = SimpleHeap(2)
s1.show()
s2.show()
}
方法区内保存类的基本信息,包括方法的实现。方法区里面的信息很少清除
Java堆内保存着s1,s2的实例
Java栈内保存着s1和s2的方法show()的局部变量
栈的溢出测试
栈帧包括:局部变量表(原生类型或引用类型的对象引用),操作数栈(类似于寄存器结构,用于计算),帧数据区(常量池指针和异常处理表)
分配最大栈内存-Xss228K
var count = 0
class SimpleHeap{
fun show(){
count++
val KB = ByteArray(1024*10)
KB.set(count, count.toByte());
show()
}
}
上面代码,我以为是保存了10K的局部变量,后来发现数组还是放在堆内存里面的,栈中只保存一个引用。所以还是能递归3000次吧
var count = 0
class SimpleHeap{
fun show(){
count++
val a = 1L
val b = 2L
val c = 3L
val d = 4L
val e = 5L
val f = 6L
val g = 7L
val h = 8L
val i = 9L
val j = 10L
show()
}
}
一共调用670次,每次调用会使用350个字节,然后局部变量会保存80字节的long型局部变量
堆内存回收分析
class SimpleHeap{
fun gc1(){
val MB = ByteArray(1024*1024*6)
System.gc() //不会马上回收内存
}
fun gc2(){
var MB: ByteArray? = ByteArray(1024*1024*6)
MB = null
System.gc()
}
fun gc3(){
{
var MB = ByteArray(1024*1024*6)
}
System.gc()
}
fun gc4(){
{
var MB = ByteArray(1024*1024*6)
}
val c = 10
System.gc()
}
fun gc5(){
gc1()
System.gc()
}
}
gc1()
可以看到没有回收内存。
gc2()
可以发现,又多分配了6MB,然后马上回收,这次一次性回收了12MB,因为gc1()的6MB也给回收了。
gc3(),gc4(),gc5()
gc3()gc4()不能为什么,根本没有分配内存,说不定给Kotlin编译器给优化了。
gc5()在gc1()退出作用域后,直接回收掉了6MB
栈上分配内存
对于那些线程私有的对象(指不会被其他线程访问到的对象),可以打散分配在栈上,而不是分配在堆上。在函数调用后自行下载,而不用垃圾收集器。
实现的技术是进行逃逸分析-XX:+DoEscapeAnalysis
/*
-server -Xmx10m -Xms10m
-XX:+PrintGC -XX:+DoEscapeAnalysis
-XX:-UseTLAB -XX:+EliminateAllocations
*/
class OnStackTest{
class User(val id:Int = 0, val name:String = ""){
}
companion object {
fun alloc(){
val u = User(5,"owen")
}
}
}
fun main(args: Array<String>) {
val b = System.currentTimeMillis()
for (i in 0..1000000000){
OnStackTest.alloc()
}
val c = System.currentTimeMillis()
println(c - b)
}
要调用100000000次,按理说会频繁调用GC,但栈上分配技术显示, 咳咳,按理说是看不到GC日志
[GC (Allocation Failure) 2047K->544K(9728K), 0.0032233 secs]
[GC (Allocation Failure) 2592K->472K(11776K), 0.0080457 secs]
60
方法区
保存系统的类信息,比如类的字段,方法,常量池。
Java1.6,1.7可以理解为永久代(Perm),设置参数为-XX:PermSize=5m,-XX:MaxPermSize=5m
Java1.8中变成了元数据区,使用-XX:MaxMetaspaceSize指定,这是一块堆外的直接内存,如果不指定大小,虚拟机会耗尽所有系统的可用内存
理解JVM2 栈内存,方法区,堆内存的更多相关文章
- JVM内存结构之堆、栈、方法区以及直接内存、堆和栈区别
JVM内存结构之堆.栈.方法区以及直接内存.堆和栈区别 一. 理解JVM中堆与栈以及方法区 堆(heap):FIFO(队列优先,先进先出):二级缓存:*JVM中只有一个堆区被所有线程所共享:对象和数 ...
- 堆、栈、方法区、静态代码块---Java
java 堆.栈.方法区 堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令) 2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基 ...
- java内存管理(堆、栈、方法区)
java内存管理 简介 首先我们要了解我们为什么要学习java虚拟机的内存管理,不是java的gc垃圾回收机制都帮我们释放了内存了吗?但是在写程序的过程中却也往往因为不懂内存管理而造成了一些不容易察觉 ...
- [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义
前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机, ...
- JVM内存的堆、栈和方法区
JVM的内存分为堆.栈.方法区和程序计数器4个区域 存储内容:基本类型,对象引用,对象本身,class,常量,static变量 堆: 拥有者:所有线程 内容:对象本身,不存放基本类型和对象引用 垃圾回 ...
- 简单了解下java中的堆、栈和方法区。
堆.栈.方法区 1,首先了解下java中的数据类型. ①java中的八大基本数据类型:boolean, char , byte, short, int, long , float , double. ...
- java中的堆、栈、方法区等比较
• 堆.栈.方法区 1. java中的栈(stack)和堆(heap)是java在内存(ram)中存放数据的地方 2. 堆区 存储的全部是对象,每个对象都包含一个与之对应的class的信息.(clas ...
- 【转载】java项目中经常碰到的内存溢出问题: java.lang.OutOfMemoryError: PermGen space, 堆内存和非堆内存,写的很好,理解很方便
Tomcat Xms Xmx PermSize MaxPermSize 区别 及 java.lang.OutOfMemoryError: PermGen space 解决 解决方案 在 catalin ...
- Java虚拟机的内存组成以及堆内存介绍
一.java内存组成介绍:堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启 ...
- 干货:JVM 堆内存和非堆内存
堆和非堆内存 按照官方的说法:"Java 虚拟机具有一个堆(Heap),堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的."" ...
随机推荐
- 启动tomcat时cmd窗口一闪而过
在tomcat的安装目录下 双击startup.bat启动时cmd窗口一闪而过 1.在系统中查看配置JDK的环境变量是否正确 2.进入tomcat的安装目录 在启动tomcat时流程是:startup ...
- 如何利用Social Listening从社会化媒体中“提炼”有价值的信息?
本文转自知乎 作者:苏格兰折耳喵 ----------------------------------------------------- 在本文中,笔者将会介绍大数据分析主要的处对象---社会化媒 ...
- <转载> nginx服务器安装及配置文件详解 https://segmentfault.com/a/1190000002797601
nginx在工作中已经有好几个环境在使用了,每次都是重新去网上扒博客,各种编译配置,今天自己也整理一份安装文档和nginx.conf配置选项的说明,留作以后参考.像负载均衡配置(包括健康检查).缓存( ...
- windows定时关机命令
at 11:00 shutdown.exe -s -t 120 https://jingyan.baidu.com/article/574c52191ea9996c8c9dc17a.html?st=2 ...
- spark快速大数据分析
从上层来看,每个Spark 应用都由一个驱动器程序(driver program)来发起集群上的各种并行操作.驱动器程序包含应用的main 函数,并且定义了集群上的分布式数据集,还对这些分布式数据集应 ...
- uri,url和urn的区别以及URLEncoder
java.net.URL类不提供对标准RFC2396规定的特殊字符的转义,因此需要调用者自己对URL各组成部分进行encode.而java.net.URI则会提供转义功能.因此The recommen ...
- ScheduledThreadPoolExecutor 使用线程池执行定时任务
转自:https://segmentfault.com/a/1190000008038848 在现实世界里,我们总是免不了要定期去做一件事情(比如上课)—— 在计算机的世界里,更是如此.比如我们手机每 ...
- Mysql索引,有哪几种索引,什么时候该(不该)建索引;SQL怎么进行优化以及SQL关键字的执行顺序
索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干,就可以得到索引的本质:索引是数据结构. 1.按照索引列值的唯一性,索引可分为唯一索引和非唯一索引 非唯一索引:B树索引 crea ...
- 解决jsfl 弹出警告
fl.showIdleMessage(false);
- Oracle函数使用
数据格式化截取: Trunc(data,[yyyy]) oracle的特有if判断: decode(sex, 0, '男', 1, '女') 分组排序:row_number() over(parti ...