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:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-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工具,没有存在的对象会进行加载,已经存在的对象就不去新增。