對象Object
里面有
Object{
Class class;//所屬的類
Slot[] slots;//實例變量
}
方法區(qū)
運行時數(shù)據(jù)區(qū)的一塊邏輯區(qū)域惶凝,由多個線程共享。
主要存放從class文件獲取的類信息,類變量也存放在方法區(qū)中抒蚜。
當Java虛擬機第一次使用某個類時,它會搜索類路徑耘戚,找到相應的class文件嗡髓,然后讀取并解析class文件,把相關信息放進方法區(qū)收津。
至于方法區(qū)到底位于何處饿这,是固定大小還是動態(tài)調整,是否參與垃圾回收朋截,以及如何在方法區(qū)內存放類數(shù)據(jù)等蛹稍,Java虛擬機規(guī)范并沒有明確規(guī)定。
我放在ClassLoader里面
ClassLoader
public class MyClassLoader {
//依賴Classpath來搜索和讀取class文件
private Classpath classpath;
//方法區(qū) 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文件并把數(shù)據(jù)讀取到內存部服;
byte[] data;
try {
data = classpath.readClass(name);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("java.lang,ClassNotFoundException");
}
- 2.解析class文件唆姐,生成虛擬機可以使用的類數(shù)據(jù),并放入方法區(qū)廓八;
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());
//放入方法區(qū)
classInfoMap.put(jClass.getName(),jClass);
return jClass;
}
- 3.鏈接:驗證和準備
link(Class class ) {
verify(class)
prepare(class)
}
prepare(JClass classInfo) {
//數(shù)實例field ,給每個實例field 編號 set一個slotId,總數(shù)存class
calcInstanceFieldSlotId(class);
//同上,這次是static Field,在class存一個這個數(shù)量的數(shù)組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里的常量池 | 運行時常量池 |
---|---|
數(shù)字(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(操作數(shù)index);
newObject={
class
slot[class.instanceSlotCount]//instanceSlotCount是類加載時按實例field數(shù)出來的
};
frame.operandStack.push(newObject);
PutStatic
field=frame.method.class.runtimeConstantsPool[指令操作數(shù)index]
field.class.staticVars[field.slotId]
GetStatic
field=frame.method.class.runtimeConstantsPool[指令操作數(shù)index]
frame.operandStack.push(field.class.staticVars[field.slotId])
Putfield
stack=frame.operandStack;
val=stack.pop;
object=stack.pop;
field=frame.method.class.runtimeConstantsPool[指令操作數(shù)index];
object.slot[field.slotId]=val;
Putfield
field=frame.method.class.runtimeConstantsPool[指令操作數(shù)index];
stack=frame.operandStack;
object=stack.pop;
stack.push(object.slot[field.slotId]);
Instanceof
class=frame.method.class.runtimeConstantPool(操作數(shù)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(操作數(shù)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);