心里种花,人生才不会荒芜,如果你也想一起成长,请点个关注吧。
class文件通过类加载器加载到运行时数据区,运行时数据区又分为线程私有和线程共享的内存;
运行时数据区的数据和方法,通过执行引擎,利用解释执行或者是JIT解释成0101的数据给操作系统
堆里面放的是一些经常变动需要回收的对象,方法区是一些静态的,不容易回收的信息,这是一种动静分离的思想
不是虚拟机内存运行时数据区的一部分,也不是JVM规范中定义的内存区域;如果使用了NIO,这块区域会被频繁使用,在Java堆内可以用idrectByteBuffer对象直接引用并操作;
不受Java堆大小限制,但受本机总内存限制,也会OOM,也会被垃圾回收
NDK用的是直接内存
Intellij IDEA 在跑的时候可以设置JVM虚拟机参数,比如-Xms等
HSDB 工具 查看JVM内存
虚拟机中对象的创建过程
类加载 --> 检查加载 -->分配内存 --> 内存空间初始化 --> 设置 --> 对象初始化
几乎所有的对象都在堆上分配,此外满足一定条件还可以在栈上分配,也就是虚拟机栈上
Eden区里只存放新生成的对象,经过一次GC后,存活的就会复制到from,然后from和to采用的是复制算法GC,复制算法GC效率高;
止于比例,大数据分析过90%的对象都会被回收,复制算法空间利用率只有50%,所以最后比例是8:1:1
因为对象的GC年龄存放在对象头中,用的是一个4位的数据,4位最多就是15;这个值可以通过JVM参数修改:-XX:MaxTenuringThreshold,改成15以下的,默认是15。CMS垃圾收集器默认是6
进入老年代后,这个GC分代年龄信息就没用了
就是在对象晋级到老年代时,有可能老年代内存会不够,但如果每次老年代都进行GC又影响性能,所以JVM会进行担保,让老年代不用每次都GC,直到内存真不够时再进行GC,这样提高性能
如果from和to区里面大对象比较多,然后年龄又还没到15,这时候也会直接到老年代
类加载 -- 运行时数据区 --- 方法区(逻辑区域)
实体类,符号引用 --> 直接引用(hash值)
运行时字符串常量JDK1.8后也在堆
String str = "ab" + "cd" + "ef"首先会生成ab对象,再生成abcd对象,最后生成abcdef对象
//会先在常量池中创建king,并在堆里面创建一个a的String对象,并引用常量池中的King
String a = new String("king").intern();
//调用intern方法之后,会去常量池里查找是否有等于该字符串对象的引用,有就直接返回引用
String b = new String("King").intern();
所以 a == b 为true;如果没有加intern方法,则不为true,因为是2个String对象
什么情况下内存栈溢出?
public class Location {
//这个地方不会在常量池中创建
private String city;
private String region;
public static void main(String[] args) {
//JVM首先会检查该对象是否在字符串常量池中,如果在,就返回该对象引用,否则新的字符串将在常量池中被创建。
//这种方式可以减少同一个值的字符串对象的重复创建,节约内存。
String str ="abc";
//首先在编译类文件时,"abc"常量字符串将会放入到常量结构中,在类加载时,“abc"将会在常量池中创建;
//其次,在调用 new 时,JVM 命令将会调用 String 的构造函数,同时引用常量池中的"abc” 字符串,
// 在堆内存中创建一个 String 对象;最后,str1 将引用 String 对象。
String str1 =new String("abc");
//这里就跟第一步类似。
Location location = new Location();
location.setCity("深圳");
location.setRegion("南山");
//首先会生成 ab 对象,再生成 abcd 对象,最后生成 abcdef 对象
String str2= "ab" + "cd" + "ef";
//new Sting() 会在堆内存中创建一个a的String对象,
// “king"将会在常量池中创建
// 在调用intern方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。
String a =new String("king").intern();
//调用 new Sting() 会在堆内存中创建一个b的String 对象,。
//在调用 intern 方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。
String b = new String("king").intern();
//所以 a 和 b 引用的是同一个对象。
if(a==b) {
System.out.print("a==b");
}else{
System.out.print("a!=b");
}
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
}
END
点赞转发,让精彩不停歇!关注我们,评论区见,一起期待下期的深度好文!