JVM 是如何实现 Java 语言的 对象系统呢?
使用 klass-oop 对象模型
深入探究JVM | klass-oop对象模型研究 
HotSpotVM 对象机制实现浅析 
CompressedOops 
Strongtalk oops 
JVM 使用 oop-klass 模型来实现 java 的对象模型。
整个 oop-klass 模型 类层次的定义在 hotspot\src\share\vm\oops\oopsHierarchy.hpp 文件中
oopsHierarchy 
oop
  1 2 3 4 5 6 7 8 9 10 11 12 13 typedef  class  oopDesc *                            oop ;typedef  class    instanceOopDesc *            instanceOop ;typedef  class    methodOopDesc *                    methodOop ;typedef  class    constMethodOopDesc *            constMethodOop ;typedef  class    methodDataOopDesc *            methodDataOop ;typedef  class    arrayOopDesc *                    arrayOop ;typedef  class      objArrayOopDesc *            objArrayOop ;typedef  class      typeArrayOopDesc *            typeArrayOop ;typedef  class    constantPoolOopDesc *            constantPoolOop ;typedef  class    constantPoolCacheOopDesc *   constantPoolCacheOop ;typedef  class    klassOopDesc *                    klassOop ;typedef  class    markOopDesc *                    markOop ;typedef  class    compiledICHolderOopDesc *    compiledICHolderOop ;
 
 
 
klass
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class  Klass ;class    instanceKlass ;class      instanceMirrorKlass ;class      instanceRefKlass ;class    methodKlass ;class    constMethodKlass ;class    methodDataKlass ;class    klassKlass ;class      instanceKlassKlass ;class      arrayKlassKlass ;class        objArrayKlassKlass ;class        typeArrayKlassKlass ;class    arrayKlass ;class      objArrayKlass ;class      typeArrayKlass ;class    constantPoolKlass ;class    constantPoolCacheKlass ;class    compiledICHolderKlass ;
 
 
 
oop的声明 hotspot\src\share\vm\oops\oop.hpp,其实现文件在 oop.cpp 和 oop.inline.hpp 文件中。
klass的声明 hotspot\src\share\vm\oops\klass.hpp,其实现文件 klass.cpp 中。
oop中实例数据的存取:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 inline  void *     oopDesc::field_base(int  offset)        const  { return  (void *)&((char *)this )[offset]; }inline  jint*     oopDesc::int_field_addr(int  offset)    const  { return  (jint*)    field_base(offset); }inline  jint oopDesc::int_field(int  offset) const                     { return  *int_field_addr(offset);        }inline  void  oopDesc::int_field_put(int  offset, jint contents)       { *int_field_addr(offset) = contents;    }inline  jint oopDesc::int_field_acquire(int  offset) const                     { return  OrderAccess::load_acquire(int_field_addr(offset));      }inline  void  oopDesc::release_int_field_put(int  offset, jint contents)       { OrderAccess::release_store(int_field_addr(offset), contents);  }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 	oop ---> +-----------+ ---} 			 |	 _mark   |    | 			 +-----------+    |---> header 			 | _metadata |    | 		{--- +-----------+ ---} 		|	 | 0x238AB801|---> +-----------+ 		|	 +-----------+     |   field1  | 		|	 |	  ...	 | 	   +-----------+ 		|	 +-----------+ data<---|	 |	  ...	 |  		|	 +-----------+ 		|	 | 0x338AB801|---> +-----------+ 		|	 +-----------+     |   fieldN  | 		|	 |	  ...	 |     +-----------+ 		{--- +-----------+ 
 
可以看到所有的 Java 对象的字段,最终是以字段的地址的列表存储在 oop 中,然后通过 offset (可以认为是 索引)获得字段所在的地址。然后使用该地址来访问对象的字段。这个 offset 应该和 字段在java 文件中的声明顺序相对应。
现在,比较有趣的就是如何针对不同的 java 类,分配不同的内存,因为不同的 java 类,拥有的字段也不同。所以 data 区域的大小自然不同。
1 2 3 4 5 6 7 8 class  C1  {	private  int  i; } class  C2  {	private  int  i; 	private  double  d; } 
 
当执行:1 2 C1 c1 = new  C1(); C2 c2 = new  C2(); 
c1 所对应的 oop 该如何分配内存呢?下面是猜测实现:
c2 和 c1 明显所占内存不同。其实也简单。当 C1 和 C2 被载入 JVM 的时候,会创建其所对应的 klass 类的对应,这个对象就是用来描述 C1 和 C2 这种 java 类的,自然这个类当然知道,C1 和 C2 内部所含有字段个数,以及所需要的内存大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 oop c1Oop; oop c2Oop; Klass c1Klass; Klass c2Klass; void * c1ptr = malloc (c1Klass.size());c1Oop = (opp)c1ptr; void * c2ptr = malloc (c2Klass.size());c2Oop = (oop)c2ptr; 
 
通过强制类型转换,解决了两个问题:
不同的 JAVA 类大小不同,所以对应的 oop 大小也应该不同,需要动态分配 
保证的类型安全 
 
下面来验证上面的推理: oops/instanceKlass.cpp instanceKlass 是 instanceOop 类相对应。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 instanceOop instanceKlass::allocate_instance(TRAPS) {   assert(!oop_is_instanceMirror(), "wrong allocation path" );   bool  has_finalizer_flag = has_finalizer();                int  size = size_helper();        KlassHandle h_k (THREAD, as_klassOop())  ;   instanceOop i;         i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);   if  (has_finalizer_flag && !RegisterFinalizersAtInit) {     i = register_finalizer(i, CHECK_NULL);   }   return  i; } 
可以看到这个方法使用 CollectedHeap::obj_allocate 来分配 oop 对象。
1 2 3 4 5 6 7 8 9 10 11 oop CollectedHeap::obj_allocate(KlassHandle klass, int  size, TRAPS) {   debug_only(check_for_valid_allocation_state());   assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed" );   assert(size >= 0 , "int won't convert to size_t" );      HeapWord* obj = common_mem_allocate_init(size, false , CHECK_NULL);   post_allocation_setup_obj(klass, obj, size);   NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));   return  (oop)obj; } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls))   JVMWrapper("JVM_NewInstance" );   Handle mirror (THREAD, JNIHandles::resolve_non_null(cls))  ;   methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror());   if  (resolved_constructor == NULL ) {     klassOop k = java_lang_Class::as_klassOop(mirror());                    if  (java_lang_Class::is_primitive(mirror())) {       const  char * msg = "" ;       if       (mirror == Universe::bool_mirror())   msg = "java/lang/Boolean" ;       else  if  (mirror == Universe::char_mirror())   msg = "java/lang/Character" ;       else  if  (mirror == Universe::float_mirror())  msg = "java/lang/Float" ;       else  if  (mirror == Universe::double_mirror()) msg = "java/lang/Double" ;       else  if  (mirror == Universe::byte_mirror())   msg = "java/lang/Byte" ;       else  if  (mirror == Universe::short_mirror())  msg = "java/lang/Short" ;       else  if  (mirror == Universe::int_mirror())    msg = "java/lang/Integer" ;       else  if  (mirror == Universe::long_mirror())   msg = "java/lang/Long" ;       THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg);     }          Klass::cast(k)->check_valid_for_instantiation(false , CHECK_NULL);      instanceKlassHandle klass (THREAD, k)  ;          klass->initialize(CHECK_NULL);          resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());     if  (resolved_constructor == NULL ) {       ResourceMark rm (THREAD)  ;       THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name());     }          java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor);   }   assert(resolved_constructor != NULL , "sanity check" );   methodHandle constructor = methodHandle(THREAD, resolved_constructor);      instanceKlassHandle klass (THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)))  ;   assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check" );      klassOop caller_klass = NULL ;   if  (UsePrivilegedStack) {     caller_klass = thread->security_get_caller_class(2 );     if  (!Reflection::verify_class_access(caller_klass, klass(), false ) ||         !Reflection::verify_field_access(caller_klass,                                          klass(),                                          klass(),                                          constructor->access_flags(),                                          false ,                                          true )) {       ResourceMark rm (THREAD)  ;       THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name());     }   }      Handle receiver = klass->allocate_instance_handle(CHECK_NULL);   JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL);   jobject res = JNIHandles::make_local(env, receiver());   if  (JvmtiExport::should_post_vm_object_alloc()) {     JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver());   }   return  res; JVM_END JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls))   JVMWrapper("JVM_NewInstance" );      Handle mirror (THREAD, JNIHandles::resolve_non_null(cls))  ;   methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror());   methodHandle constructor = methodHandle(THREAD, resolved_constructor);         instanceKlassHandle klass (THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)))  ;         Handle receiver = klass->allocate_instance_handle(CHECK_NULL);         JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL);      jobject res = JNIHandles::make_local(env, receiver());   return  res; JVM_END 
 
JVM_NewInstance 使用 klass->allocate_instance_handle 来分配内存,其实现代码如下:
1 2 3 instanceHandle allocate_instance_handle (TRAPS)        { return  instanceHandle(THREAD, allocate_instance(THREAD)); }
 
对象分配 使用 java 语言的 new 关键字分配对象的实现过程:
参考:<<HotSpot实战>> 3.3 创建对象
hotspot\src\share\vm\interpreter\interpreterRuntime.cpp InterpreterRuntime::_new
interpreterRuntime.cpp中有很多 java 关键实现,
例如:monitorenter 指令的实现,InterpreterRuntime::monitorenter
monitorexit 指令:InterpreterRuntime::monitorexit
java创建对象的方式 
new 关键字的实现,参考: hotspot\src\share\vm\interpreter\interpreterRuntime.cpp InterpreterRuntime::_new
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 IRT_ENTRY(void , InterpreterRuntime::_new(JavaThread* thread, constantPoolOopDesc* pool, int  index))   klassOop k_oop = pool->klass_at(index, CHECK);   instanceKlassHandle klass  (THREAD, k_oop)  ;      klass->check_valid_for_instantiation(true , CHECK);      klass->initialize(CHECK);                                             oop obj = klass->allocate_instance(CHECK);   thread->set_vm_result(obj); IRT_END 
 
调用 klass->allocate_instance(CHECK); 来创建对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0))   JVMWrapper("JVM_NewInstanceFromConstructor" );   oop constructor_mirror = JNIHandles::resolve(c);   objArrayHandle args (THREAD, objArrayOop(JNIHandles::resolve(args0)))  ;   oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);   jobject res = JNIHandles::make_local(env, result);   if  (JvmtiExport::should_post_vm_object_alloc()) {     JvmtiExport::post_vm_object_alloc(JavaThread::current(), result);   }   return  res; JVM_END oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args, TRAPS) {   oop mirror             = java_lang_reflect_Constructor::clazz(constructor_mirror);   int  slot               = java_lang_reflect_Constructor::slot(constructor_mirror);   bool  override          = java_lang_reflect_Constructor::override(constructor_mirror) != 0 ;   objArrayHandle ptypes (THREAD, objArrayOop(java_lang_reflect_Constructor::parameter_types(constructor_mirror)))  ;   instanceKlassHandle klass (THREAD, java_lang_Class::as_klassOop(mirror))  ;   methodOop m = klass->method_with_idnum(slot);   if  (m == NULL ) {     THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke" );   }   methodHandle method (THREAD, m)  ;   assert(method->name() == vmSymbols::object_initializer_name(), "invalid constructor" );      klass->initialize(CHECK_NULL);      klass->check_valid_for_instantiation(false , CHECK_NULL);   Handle receiver = klass->allocate_instance_handle(CHECK_NULL);               invoke(klass, method, receiver, override, ptypes, T_VOID, args, false , CHECK_NULL);   return  receiver(); } 
 
调用 klass->allocate_instance_handle 创建新对象实例。 allocate_instance_handle 内部使用 allocate_instance 来创建对象。
所以,对于一个 java 对象,最终是由其所对应的类型的 Klass 的 allocate_instance 方法来完成内存分配的。
$. 参考 
Dangerous Code: How to be Unsafe with Java Classes & Objects in Memory  
Getting Started with HotSpot and OpenJDK  
源码分析:Java对象的内存分配  
HotSpotVM 对象机制实现浅析