快捷搜索: 王者荣耀 脱发

方法区内存溢出及常量池

22 方法区-定义

是所有线程共享的一块区域。
存储了和类结构相关信息。运行时常量池,
方法区在虚拟机启动时被创建,逻辑上是堆的组成部分。

方法区内存不足,也会导致oom异常。
是一个概念上的东西,
1.6使用永久代作为方法区,类和类加载器。还有运行时常量池,串池。
1.8 Metaspace 元空间,类,类加载器,常量池,不占用堆空间,不由jvm管理,占用操作系统内存。

23 方法区——内存溢出

ClassLoader 用来加载类的二进制字节码。

循环1000次,是否会因为类加载过多,导致方法去内存溢出。
-XX:MaxMetaspaceSize=8m  演示元空间内存溢出问题。

1.8以前导致永久代内存溢出;
1.8以后导致元空间内存溢出。

24 内存溢出

场景
spring
mybatis
	都使用了cglib,动态代理核心

25 方法区——常量池

什么叫常量池?
	javap -v Helloworld.class 反编译
	
java源代码变成虚拟机指令。
查表翻译  #2
查询常量池的表。
给指令提供一些常量符号,查表方式找到他们。

26 方法区-运行时常量池

是一张表,虚拟指令从里面找,执行的类名,方法名,参数,字面量等信息。
运行时常量池,当类被加载,它的常量池就会被放到运行时常量池(内存中),地址变为真实地址。

27 StringTable面试题

28 常量池和串池的关系

ldc #2 把a符号变为"a"字符串对象。
每个字符串对象都不是事先放到串池,而是用到才开始创建字符段对象,是懒惰的行为。

StringTable ["a","b","ab"] hashtable结构,不能扩容。

astore 存储
aload  从表中拿到

29 字符串变量拼接

测试代码

public class Demo1_22 {
          
   

    public static void main(String[] args) {
          
   
        String s1="a";
        String s2="b";
        String s3="ab";
        String s4=s1+s2;
        System.out.println(s3==s4);
    }
}

//new StringBuilder().apend("a").append("b").toString()  new String("ab")

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mSXxsJia-1691329173338)(C:UsersAdministratorAppDataRoamingTypora ypora-user-imagesimage-20230806163553488.png)]

30 编译器优化

javac在编译期的优化,都是常量,拼接的结果已经确定了。

代码

public class Demo1_22 {
          
   

    public static void main(String[] args) {
          
   
        String s1="a";
        String s2="b";
        String s3="ab";
        String s4=s1+s2;
        String s5="a"+"b";
        System.out.println(s3==s5);
    }
}

31 字符串延迟加载

使用menmery工具,没有存在的对象会进行加载,已经存在的对象就不去新增。
经验分享 程序员 微信小程序 职场和发展