目录
1、栈、堆和方法区的交互关系
1.1、运行时数据区结构图
①、从结构上的角度看
②、从线程共享与否的角度看
1.2、堆、栈和方法区的交互关系
2、方法区的理解
2.1、官方文档
2.2、方法区在哪里
举例说明 :方法区看作是一块独立于堆的内存空间
package com.atguigu.java;
public class MethodAreaDemo {
public static void main(String[] args) {
System.out.println("start...");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end...");
}
}
设置堆大小:-Xms600m -Xmx600m
查看内存大小分布:
2.3、方法区的基本理解
2.4、Hotspot中方法区的演进
2.5、方法区的概述
3、设置方法区的大小与OOM
3.1、设置方法区内存的大小
package com.atguigu.java;
/**
* 测试设置方法区大小参数的默认值
*
* jdk7及以前:
* -XX:PermSize=100m -XX:MaxPermSize=100m
*
* jdk8及以后:
* -XX:MetaspaceSize=100m -XX:MaxMetaspaceSize=100m
* @author shkstart shkstart@126.com
* @create 2020 12:16
*/
public class MethodAreaDemo {
public static void main(String[] args) {
System.out.println("start...");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end...");
}
}
JDK8环境下:
切换到JDK7环境:
方法区内存溢出举例:
package com.atguigu.java;
import com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* jdk6/7中:
* -XX:PermSize=10m -XX:MaxPermSize=10m
*
* jdk8中:
* -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
*
*/
public class OOMTest extends ClassLoader {
public static void main(String[] args) {
int j = 0;
try {
OOMTest test = new OOMTest();
for (int i = 0; i < 10000; i++) {
//创建ClassWriter对象,用于生成类的二进制字节码
ClassWriter classWriter = new ClassWriter(0);
//指明版本号,修饰符,类名,包名,父类,接口
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null);
//返回byte[]
byte[] code = classWriter.toByteArray();
//类的加载
test.defineClass("Class" + i, code, 0, code.length);//Class对象
j++;
}
} finally {
System.out.println(j);
}
}
}
JDK8环境下: -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
JDK7环境下:-XX:PermSize=10m -XX:MaxPermSize=10m
3.2、如何解决这些OOM
4、方法区的内部结构
4.1、方法区(method area)中存储什么?
package com.atguigu.java;
import java.io.Serializable;
/**
* 测试方法区的内部构成
*/
public class MethodInnerStrucTest extends Object implements Comparable<String>,Serializable {
//属性
public int num = 10;
private static String str = "测试方法的内部结构";
//构造器
//方法
public void test1(){
int count = 20;
System.out.println("count = " + count);
}
public static int test2(int cal){
int result = 0;
try {
int value = 30;
result = value / cal;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
@Override
public int compareTo(String o) {
return 0;
}
}
package com.atguigu.java;
/**
* non-final的类变量
*/
public class MethodAreaTest {
public static void main(String[] args) {
Order order = null;
order.hello();
System.out.println(order.count);
}
}
class Order {
public static int count = 1;
public static final int number = 2;
public static void hello() {
System.out.println("hello!");
}
}
javap -v -p Xxx.class ##查看信息
4.1.1、类型信息
4.1.2、域(Field)信息
4.1.3、方法(Method)信息
4.2、non-final变量
4.3、全局常量(static final修饰)
4.4、运行时常量池 vs 常量池
4.5、为什么需要常量池?
4.6、常量池中有什么?
4.7、运行时常量池
5、方法区的使用举例
5.1、举例说明
package com.atguigu.java1;
/**
* @content 方法区使用举例
* @version v1.0
*/
public class MethodAreaDemo {
public static void main(String[] args) {
int x = 500;
int y = 100;
int a = x / y;
int b = 50;
System.out.println(a + b);
}
}
6、方法区的演进细节
6.1、演进细节
6.2、为什么用元空间替换永久代?
6.3、StringTale为什么要调整?
6.4、如何证明静态变量在哪?
package com.atguigu.java1;
/**
* 结论:
* 静态引用对应的对象实体始终都存在堆空间
*
* jdk7:
* -Xms200m -Xmx200m -XX:PermSize=300m -XX:MaxPermSize=300m -XX:+PrintGCDetails
* jdk 8:
* -Xms200m -Xmx200m -XX:MetaspaceSize=300m -XX:MaxMetaspaceSize=300m -XX:+PrintGCDetails
* @author
* @create
*/
public class StaticFieldTest {
private static byte[] arr = new byte[1024 * 1024 * 100];//100MB
public static void main(String[] args) {
System.out.println(StaticFieldTest.arr);
}
}
package com.atguigu.java1;
/**
* 《深入理解Java虚拟机》中的案例:
* staticObj、instanceObj、localObj存放在哪里?
* @author
* @create
*/
public class StaticObjTest {
static class Test {
static ObjectHolder staticObj = new ObjectHolder();
ObjectHolder instanceObj = new ObjectHolder();
void foo() {
ObjectHolder localObj = new ObjectHolder();
System.out.println("done");
}
}
private static class ObjectHolder {
}
public static void main(String[] args) {
Test test = new Test();
test.foo();
}
}