第6章 方法区 运行时常量池 类加载器

对象Object
里面有

Object{
  Class class;//所属的类
  Slot[] slots;//实例变量
}

方法区

运行时数据区的一块逻辑区域,由多个线程共享。
主要存放从class文件获取的类信息,类变量也存放在方法区中。
当Java虚拟机第一次使用某个类时,它会搜索类路径,找到相应的class文件,然后读取并解析class文件,把相关信息放进方法区。
至于方法区到底位于何处,是固定大小还是动态调整,是否参与垃圾回收,以及如何在方法区内存放类数据等,Java虚拟机规范并没有明确规定。

我放在ClassLoader里面

ClassLoader

public class MyClassLoader  {
    //依赖Classpath来搜索和读取class文件
    private Classpath classpath;

  //方法区 key是类的完全限定名
    private Map<String, Class> classInfoMap=new HashMap<>();
  
  
    public Class loadClass(String className){

        Class class = classInfoMap.get(className);

        if (class==null){
            classInfo=  ......
            classInfoMap.put(className,class);
        }
        return class;
    }
}

类的加载大致可以分为3个步骤:

  • 1.找到class文件并把数据读取到内存;
byte[] data;
 try {
  data = classpath.readClass(name);
} catch (Exception e) {
   e.printStackTrace();
   throw new RuntimeException("java.lang,ClassNotFoundException");
}
  • 2.解析class文件,生成虚拟机可以使用的类数据,并放入方法区;
    JClass classInfo = defineClass(data);
 private JClass defineClass(byte[] data)  {

        //byte[] -> classFile ->class
        JClass jClass = parseClass(data);
//并把其父类和接口也加载
       jClass.interfaces = resolveInterfaces(jClass.getInterfaceNames());
        jClass.superClass = resolveSuperClass(jClass.getSuperClassName());
//放入方法区
        classInfoMap.put(jClass.getName(),jClass);
        return jClass;
    }
  • 3.链接:验证和准备
 link(Class class ) {
  verify(class)
  prepare(class)
}
prepare(JClass classInfo) {

//数实例field ,给每个实例field 编号 set一个slotId,总数存class
        calcInstanceFieldSlotId(class);
//同上,这次是static Field,在class存一个这个数量的数组Object[] staticVars;
        calcStaticFieldSlotId(class);

//给final static的field赋值, 
//这些field的属性里面有常量池index是初值,
// 按其slotId放入类的staticVars
        allocAndInitStaticVars(class);
    }

类信息

JClass {

///////////////////////////////////////////直接copy来classFile
    @Getter(AccessLevel.NONE)
    private int accessFlags;// uint16 类的访问标志

    //完全限定名,具有java/lang/Object的形式
    private  String name;// thisClassName
    private  String superClassName;
    private  String[] interfaceNames;
    private RuntimeConstantPool runtimeConstantPool;//存放运行时常量池指针
    private Field[] fields;
    private Method[] methods;

/////////////////////////////////////////////////////////类加载时加工填充的
    public MyClassLoader classLoader;//加载时保留加载器引用
    public  JClass superClass;
    public  JClass[] interfaces;
    public int instanceSlotCount;
    public int staticSlotCount;
    public   Object[] staticVars;
}

对象

{
   JClass jClass;//所属的类
    Object[] slots;//实例field的值
}

Field

{
//类成员都有的部分
    protected     int accessFlags ;//classFile复制
    protected    String  name;//classFile复制
    public     String  descriptor;//classFile复制

    protected JClass jClass;//所属的类

    int constValueIndex ;//classFile得 在属性里 字段的初始值index

//static是类的staticVars的id  实例field是对象里面slots的id
     private   int slotId          ;//类加载时计算
}

Method

{
//类成员都有的部分
    protected     int accessFlags ;//classFile复制
    protected    String  name;//classFile复制
    public     String  descriptor;//classFile复制

    protected JClass jClass;//所属的类

//来自Code的属性
  private int maxStack ;
  private int maxLocals ;
  private   byte[]  code ;
}

运行时常量池

用classFile里的常量池 转的 index不变 没有就空着

classFile里的常量池 运行时常量池
数字(i l f d) 原样
UTF8
STRING(引用UTF8) 字符串
ClASS(引用UTF8) 类引用(类名,使用类[能拿类加载器])
NAME_AND_TYPE(引用UTF8)
FIELD_REF(引用ClASS,NAME_AND_TYPE) field引用(类引用,名,描述)
METHOD_REF(引用ClASS,NAME_AND_TYPE) method引用(类引用,名,描述)
INTERFACE_METHOD_REF(引用ClASS,NAME_AND_TYPE) method引用(类引用,名,描述)

classFile里的常量池有所属类的引用 , 每个常量都有对常量池本身的引用

类和对象相关指令

new


class=frame.method.class.runtimeConstantPool(操作数index);
 newObject={
    class
     slot[class.instanceSlotCount]//instanceSlotCount是类加载时按实例field数出来的
};
  frame.operandStack.push(newObject);

PutStatic

field=frame.method.class.runtimeConstantsPool[指令操作数index]
field.class.staticVars[field.slotId]

GetStatic

field=frame.method.class.runtimeConstantsPool[指令操作数index]
frame.operandStack.push(field.class.staticVars[field.slotId])

Putfield

 stack=frame.operandStack;
 val=stack.pop;
 object=stack.pop;
 field=frame.method.class.runtimeConstantsPool[指令操作数index];
 object.slot[field.slotId]=val;

Putfield

field=frame.method.class.runtimeConstantsPool[指令操作数index];
 stack=frame.operandStack;
object=stack.pop;
stack.push(object.slot[field.slotId]);

Instanceof

 class=frame.method.class.runtimeConstantPool(操作数index);
 stack=frame.operandStack;
 object=stack.pop;
 if(object.class isInstanceOf class){
    stack.push(1);
 }else{
   stack.push(0);
 }

Checkcast

object=stack.pop()
 stack.push(object);
 class=frame.method.class.runtimeConstantPool(操作数index);
 
 if(!object.class isInstanceOf class){
    throw new ClassCastException();
 }

用于


if (xxx instanceof ClassYYY) {//Instanceof
        yyy = (ClassYYY) xxx;//Checkcast
// use yyy
 }

Ldc

Object constant = frame.method().class().runtimeConstantPool[index]
operandStack.push(constant);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 字节码查看工具:WinHex 前言 Java虚拟机实现语言无关性的基石就是Class文件Java虚拟机提供的语言无...
    zlcook阅读 7,114评论 4 18
  • 1.流程 创建 HelloWorld.java代码如下package jvm; /** * @author ...
    RunAlgorithm阅读 1,326评论 4 6
  • 喜欢上摇滚,不单只是喜欢它那种震撼人心的力量呐喊,更加喜欢它特有的魅力-简单,真诚。 作为一名90后,受益前辈们的...
    天水清波阅读 676评论 0 0
  • 美国硅谷出了一个吊炸天的科技狂人,他的名字叫Elon Musk--埃隆·马斯克。为何说他是科技狂人呢?那么我们来看...
    岱挚阅读 498评论 0 1