揭开java 对象在内存中的面纱
前情提示:
堆中的 java 对象只有数据部分,对象中的数据的含义要结合方法区中的class 才能明了
对象的内存结构图:
延伸:二维数据对象的内存结构!
使用 jhsdb hsdb
工具查看真实地址中的 java对象
注意:java 虚拟机为了节约内存,对堆内存中的对象的对象属性地址都进行了压缩
class 指针地址在前补一位8
即为真实地址:如 0x00c00a00 => 0x800c00a00对象地址则左移 3位:0x e2b6 1148 => 0x 7 15B0 8A40
java 对象的类对象、静态变量到底存放在哪块地址
1)、类对象(Class 对象):
- 存储在堆中
- 静态变量:紧挨着类对象
2)、类的字节码:
Student.java => student.class() => JVM (方法区)
- 通过类对象可以间接访问类的字节码
- 类的字节码读到内存之后会被封装为一个c++ 对象 (
klass 类型
)
类的字节码在jhsdb 中的真容:
class Student {
public static int count = 0x777;
private static String crissy = "crissy";
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public Student() {
}
public String myFun() {
return crissy;
}
}
java 对象的六种创建方式
public class CrissyMain {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, CloneNotSupportedException {
/**
* java 对象的六种创建方式
*/
//TODO 1. new 创建对象
System.out.println("new 创建对象:");
Student student = new Student(100, "hui");
System.out.println("hashCode:"+student.hashCode());
System.out.println(student);
//TODO 2. 通过反射创建对象
System.out.println("通过反射创建对象:");
Constructor<Student> constructor = Student.class.getDeclaredConstructor(int.class, String.class);
Student student1 = constructor.newInstance(101, "crissy");
System.out.println("hashCode:"+student1.hashCode());
System.out.println(student1);
//TODO 3. 克隆对象 --前提是该类需实现 Cloneable 接口并 重新 clone() 方法 《浅克隆并且不会调用构造方法》
System.out.println("通过克隆创建对象:");
Student student2 = (Student) student1.clone();
System.out.println("hashCode:"+student2.hashCode());
System.out.println(student2);
//TODO 4. 反序列化创建对象 -- 前提是该类需实现 Serializable 接口
System.out.println("通过反序列化创建对象:");
Student student3 = (Student) SerializeUtil.deserialize(SerializeUtil.serialize(student1));
System.out.println("hashCode:" + student3.hashCode());
System.out.println(student3);
//TODO 5.MethodHandle API
System.out.println("通过MethodHandle API创建对象:");
MethodHandle methodHandle = MethodHandles.lookup().
findConstructor(Student.class, MethodType.methodType(void.class, int.class, String.class));
Student student4 = (Student) methodHandle.invoke(200, "----crissy");
System.out.println("hashCode:" + student4.hashCode());
System.out.println(student4);
//TODO 6.通过Unsafe API创建对象 (略---java包找不到它的API 了)
}
}
class Student implements Cloneable, Serializable {
public static int count = 0x7777_8888;
private static String crissy = "crissy";
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
System.out.println("---全参构造方法被调用");
}
public Student() {
System.out.println("---无参构造方法被调用");
}
public String myFun() {
return crissy;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "{ id:" + this.id +
", name:" + this.name +
"}";
}
}
输出结果:
new 创建对象:
---全参构造方法被调用
hashCode:584634336
{ id:100, name:hui}
通过反射创建对象:
---全参构造方法被调用
hashCode:2052001577
{ id:101, name:crissy}
通过克隆创建对象:
hashCode:1160264930
{ id:101, name:crissy}
通过反序列化创建对象:
hashCode:1555845260
{ id:101, name:crissy}
通过MethodHandle API创建对象:
---全参构造方法被调用
hashCode:1761291320
{ id:200, name:----crissy}
通过Unsafe API创建对象: