前言

  在上一篇文章中,我们花了较大的篇幅去介绍了JVM的运行时数据区,并且重点介绍了栈区的结构及作用,相关内容请猛戳!在本文中,我们将主要介绍对象的创建过程及在堆中的分配方式。

  相关链接(注:文章讲解JVM以Hotspot虚拟机为例,jdk版本为1.8,个人技术博客www.17coding.info
  1、 你必须了解的java内存管理机制-运行时数据区
  2、 你必须了解的java内存管理机制-内存分配
  3、 你必须了解的java内存管理机制-垃圾标记
  4、 你必须了解的java内存管理机制-垃圾回收

对象的创建

  在上文我们提过一些问题,你的对象是怎么new出来的?new出来又放在哪里?怎么引用的? 老规矩,我们还是通过字节码来了解一下。

public static void main (String[] args){
  People p = new People();
}

  这样的代码大家一点也不会陌生,我们都知道使用new关键字可以创建一个对象,对应的字节码如下

 aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvcAAADqCAMAAAFmcapzAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAYUExURQAAAMDAwCEAAMinp3onDPNOGIonDAAAAJ+OkZ4AAAAIdFJOU/////////8A3oO9WQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAGpZJREFUeF7tnYtimzoMhtd0Z+//yEfSr5uNSSCBAIm+ButmG1sohHZb9+cT+FE5x6P4feZGm1/lz5+f185jpFm6U7yGT0LKjQ1dLy1c5FJuKof8EH9uBOtwrUPH9jw113Pc3d8DHo/db3bKvHVoKnFh6h4s7L89+KuTM1Q2qimr3k6/Klvy/MOy6snnFBX2jacfLCfmXzL5HPNjJ/OvSYmzZH4nzjBzLnKPIlMfeQbzEzMTM9PCVQeLdhxb4/m3453zt7u7GHp5ZA9X3ojt4apcff3bU+k4K/2V2fFKbTn12sfltcjs+zxOKIuehGZ4OPb2wvSvjN2AuK7NFd7kcusD78bo5ERSjdfXnR5PBvO/Tp7/lQs/N9bnv72w/jsLa/IzSfdM/hdflp+35n+DcpnwxvUXRVFcgB1utC/BD7RYk7TcuBImHXhxY05qIYzWOp6zrWcMJVRe0NtVk36hfM9BD1GHPNkvPq9n2BLMSecvDL81ie8uwi7YeV9h8e43Zt15Jc+DjB713eAG5z1k3cRz5+Xc0wVgQXuXL7HEzx0EaO7b9j1g530O++bi+RleY/l5/46+ZaHl85+Zcst/ejpmXb5xieTLBDtUSWf5ud3IqYGH55hb/kW4v/zI01tYX6qXyH6bQakqqPO1rx3Ql6sRL3GjsSkWQSOpv8zElkqZRWfz6dBPA417ykfXPqcB+44snIrx8q/DaPmEJZuzLtmHWewMco13vnwh8SJO+g74QCzvmnxpi3fhVS9U9ouiuAKH3KvipKzNLyFHxvr82B3hpxyT+DJUow8D1trDtN53YfKmDueCucSSkcN2+dk61cZsoVi00XrxZd58nJa0uNkfJu28gU1+3rrJJE+w5LxWJONMTn3siTGHg6qeWdDtl1LQJuEty7+98rP+4Mxl8xhJwgE8cd5BOVwn96d5K27HdZJ/dax4RNI7x/6VGdvzhbVxyT17p7D7Ph38zz1pFiws+bU12yKbwet+4T6nPzu/ArriBnVe4O06v/xH5bC2XKb94TE/y7bPdMSEmeV75c1X9dJ6t354h/gY+Z45vjSu77QY8YDZ5R9RO1j8mvPOFc/7107QSVeed275dgFPzvzyL8FopbeDlv9EwX5g9tl5/6bFsfXvjekIeMw/nTVHQqa1zS5fesQwDMER+hKsN2RifOcXiQOekGZZlJhb/nH40pZwvuWvYn75kwt1RuaWj0VbNZ52E/PZvwTj5V8HXfGUS9T+I+JeWxSLyUUDndsLlFJaJglY0RbFXdoiuVzJWK0XxWo+qPbrHVAURVEUxUcijzvxzDNmFBNfF2jM6SD8MULL7BDTB2MuDz9l8r6kheKIKu5RDOO4MTer1ld82uQvQeKwsi8fEKp8KkgCvvglhyKquKcxc0EiwKr1hYeJuVXrdEjzCxJnaQrrKotiYwal9ajavDD7jlTNk7Fa6cZ0yMT1NfDG7RDUkJThpY3CuvmpzV/8ghALrfryAcGtkfUvIhKVIMMS5/7cwf06ml6/9jdXxcSc9jaALqrGWaqDhcUuxAt/53Rb8J+ZjP9Lk09kw/1Slc5VHvlzYZoelQ2bFoF1qC0xk+bQQ3wXx/f7Mp4U+8p0Fl0ldNd+GuYS8Oxn0BmN69cn9vsqmhRJpyYXjYU81Wqbj/jlX932y7qsJWISRUuNSehiXRPcbkTj5iDo4wafOL6az2an/UYdrqlIOj9Ws91CTs2O+9U7wtL06wK+JO977tfu0H6nXnAFvibtyhn2y2vAOr4j+8ft194AIvlTnl6/3bsif3+w4A0z7bRo0AHoft+Wc8kDNfYo6Hm5ye+/xsfNb/ilH15K1ixms2m0850SzftbHydycqCKlNTzf+gp65A4kHhjdzFRItEizQ1xRrBT2+970b8UX2zKzK887bF/jIDa1Kv/XBHQFNtWOM8WM87+PMoZdeh8jcnfqwu+38fnWMLfdcnnc+Ked8v/0+3KpXD3TVYP+ulI55vawM2HB1S40tvmu9G99ef31/crE2jsNVYmn09pn7NYCHzriPv9LtDkd5Ovhtrmae108Gb5V96Hi1q8XmRt8vmNx49b38Ku+12TfFqDFL3z+rU/NbLVvRLPLEo+LeDGlS/Zd1jF8WkXgferclceJ1+/p+PK55/RE5pr3Ffx9UHofknsdrsxFiWfF2EfuB+P7vcdLLjtYCmW/FTlXcHP1r+9U6wDydm+T8GzYcb8LhxpwbzPU990mb6/pz+/otZ8k5iSuqz7wBXaWdmyG097pMWSIlbr2A6eS+fz8+opUkhQG51EwTFnm0+k/kgEBwKsG6Kbj5scZNw25Znk21hTVdrGsy5IXBolxTbGEmSnwxFnUx8cqogBT2vnI6k4qMVLDhC+LhB641+d/GI7ViY/X8y7LO74zbxQ+fzWkxxT08hiIWuTz9nVDE+SD7VYzIrkF9uzMPmgKvtIcvbtdtPLYh8syUYkHc4UKoqLY9Vt5OpuKl0NFtv8GWeBnFIjSW0P+WaedXfol76KV5EkajJxRIpVAuljEXlpUxRXRu7jfSVPyrtKfR80+SqcOb3YEs26ioQ6hTZSFNdn7p6fXVX3e6HJV5FIVhsoNkOzrsIRXR3ZXxRF8Yi6ZxRFURRFURRFcQz03cgHf0MiW+Pm3h5HMfjaiFusDAYNXER4J/HxgELYOTk8/QfmH1tKfxmBCGu64b5nI1Oo7Tem6eNTQJnEkvk52Mamm7O/AjXaNmIWiY7Rt9W4f3hMpwy70zxGirGMwMdgO85bC0s3LSZ8fc9GsvAwKV04u6Agv/Bxm2dHTNViNUuSdq8PxegCxHujKM7MqFDvF+93l/Z093fzkYODjuOx4X0U/y4W7ntJt1GfR+O+Ne0Cbx6HfZkXhG8NzRhVY+42lqwvgzKRnikiD6Y1mZrAMR6b+0CPOcNjpBjJ6Pdt8MZx4AtAml/VLE1xv/5SHkYU5Bc+bmNui12bd/1+mAwndJI4WshoLfcSfOnkz+z3/eD3Mu3+25lOw4n2S2vAMr4k+dvtl28hqo7hqPXIusG/UhnLwFqa/qSIbhLqten2uzGaHsocaylZnSm/P1zXQm/BaX+QPh4msYthed/pF+A1iWLDHchhxAkrellI39+0NCKp1yTvdyskadSkGmXEDdVwF195/JbTWEnXvxs6cFwI/YjVY0soK17XnqFRqsxHtxtdR/ya2b6/2aN5rgbtUferzcasyZEtJH1P9dHEfo8Gv/fzHGt5B6fZL5ZA7cHreBe77feZezKWsfVKzssu+00JV/XhJeAV8P/1uv1izslu+00Jt2MpX5H4xOb7bXLPP8dfgCziizK/836t5ulYkP4vyrtwlv3yOr4p92fYL33W0BJ0FV+Q/DPtNxbyHRy433TX5/8WSp6w7L9Gc9qPhscfFH2PZR/t78f2e2Sx4blH/rvJu4+32g/GQmTMOXP/cL/bE4mQPwIx00rAF8LRnLRxAqNPLxnVx0OPZbLf/bH3f5cpu/784g8fAhHvZ0qCXXJQ4/Omfv59RPKdhMF+3wEngg55paTcyMJiFK1772JKGqVhpDjiaCUiuofOBG+02e+b+Ku/xL3YFM3ufSr3u6DZvU/3f0bghvf2d98M6V61iFHfe+P5WZrl1vtdl/tYIa/j2Y+ctblaxxYzT+eQv/Li+91m9Wvrns5Kr1cetJ555r/L2ulGfe+Np9ht8t3jFqzPvb7/br+yYErkmn0TK7uvol2MrE811XPYfA73ajoQ2O/PDz9Xon/06PuuZU3uOem/1NiL1sE1bM/kC/Fn+B3hM0yXxg5VCV5Hjk/fj7xDzjxevx5Hn9f3sfp+j8svNx2sY+0K0H/tqHmwCuCrERER+OnAC3o6pj6GJCVfrOF+Q3uOxbn/Ry2dXxqRHw7vcef9rqt7W8y3sO9+l9f9l+VdHylE34kVdc/rwN1PefV+d3Jkv1D3YVnub5Z7zren/HNzL1vdNe/Mwrr/p8+YTbrZWP+ccwnekvwluac1WO6bTCP3re8ToH2eIvf6RwZ0z8GHD+XZU428f1bm449IsN89WXTPuaHuvwa5APvzsO6xDn2+/3x0v29hQd2fPve4961j1F99w9zfn/9eNMfafg9zj9ue5T4N7s43e3oLRAfWZru/RPrxVjrBqnP5bX46qvU0lhrma2TvdGXR/b6te5/jOaY/L3yRNN34R4sD56jfcKwisXsdZrAhvRTW5b4/ezzlkBSVm/i54OgpyLvtAHIfZ4fe2TCViIPRmmHH3LlH37eNTuJkhmdl7ieFRWcSF84YPxNnGX3zqM3rviPOa+fJ5yI9mbFeMFpbtiIOb5wrk3x9mOwY8uo9x4wscR0g1W9hwmJbwTO1s5knH9yqjhf0dEx9DEm8FMSyHbphnhTDsI4ncl88SZ/8yv1xVO6PY23uJzetIcOPoKLj1c/aGSr3C1iZ+0lOzcGf6ayrXblfwPP3e8m051gzb47K/QJeuOeIlIzLAbcGVRT3eL7ui1dZnPtiBzS796nc74JmdyF1Iz8Oyn2l/xhS3pvnebHwVexF5FYy7w/4lvXK/X5QbjW9kWscYRdFURRXJd/F07NM64YZTbEDKzJbF2ETUO90yHMlS3lpBBoz0opXoQxz3lPuzWdZhtTWn/2L58mZTQdeokMS7mMaoyiKorgIfOvub9/y0as6U7f3NyLJzhegsr8neKrRHIvI+a7c74s+50O1Rqnc7wvnN3IvWphFURTFxeF7eX8/x0du9tYd/21Y7j3llfs9mT7fJyr1O9M/32cq+fvC+c25p8ZT7kpRFMVd6m5xHJX746jcF99I1f1xVO6LoiiKoiiKoiiKoiiKwzjFD6d+5K8UoK2fl10fvYL290TWsnTc8/3MsXCGxefRCu6YPYv7VVl4nuJUxFVbev36fi9c91VD155nWX/pFc0CvJ8pSwcWx0F3MbmReaM2W2jNTJqg90UVHjZbzUYj2PAOTT+2o6NYuYML06LMcgduQ2tQ06LWgUTTM7qxmxtXxB2aKdwwpqh0f3FC7NL1UhuXZhlhu4YyWDDOjtRkVSAVL2rgTm00gmrSzw4W0YNxy/tx43oCtno9mLzUsEwexhR3FOdFLhI1vdTGpVkNqR+3bc/WcuiGCdE0WRVIlRe74E5tdhCs2EGNCrUdWOYXixp4A/N7xDtAsZC7+w4pUpwX/tyGQpJfatvHuEl0CMLvA1SBiLj3U9TSOAvxsIieavmLHSq04U7SqtR+7lVbu5LUUfD7PPAN+sHlpirewOkNA6Uzi1Mi1/HKoBxf4NkJHo6rui86pCSeLbh9qWot7vJ80epAK34xmIczIv6oV8w8nHDZWWTseILiY3nqci8dZP0g15xq6QjuIb2iWcMLQ4vLYvdJFW7HLdAVcfIL0VBSP+nSYCZkBGO8tqEBlSY0ah1IaM/cmpsbV8QdmincMFCodU/x8VgJNBIq6BRpowkV5gALpP6K6lKGdrCAVCtGeD9uXI94a7s7ealh6SFgHTp38cnIxaamuejZ7hRpowkV5giNpP6KDROf1t3P7Xb7vZmTgWL90Mm8hCrmbx0MFAu52zGPvt2KfaHre+PrezT8qc+XXD/+WaAARLppCjoLEUj9zJ2Bw3tHT2lsRmluYlPhaxcMgIIXGdzYkEk/6RmmKt7A6Y2LpBT7gYo/ReGvQupnC1COUyQlS9IyN8EjfFzV+REsvr7fgWQj3QbO8VlYbMWJr+/a+5/25/snqyaBWGRaI8CfOoSCLORk3LqOJg3Y0upE7mVbxXRccQSD66vyMLhIVK4iV9t0it7P0g4A7ReqZgQCzbL5w2nV7Xa05irejpb34PpycxxxO9TicFMDJr2uFHyLaL42RmBIkjYLNwJrtx+7BeTE0Icgf2PLHax7DDPco4p+y9oN8V7FEdzsuk6v7+E0dcKg3NMxBIVs4Um3JmAdTQrq6RMjLfFgfgZODaE/K9KqNKM4irnrezhNnUhrh9MYQFzU9NIwtY+L5M3jp/RkU0LESUq6DzT9kzTChrO3p/7ibcj17Qq+u75Hw7dJLguTpPDL68X94nXEGY15nLBIQy/xiPyhh3pu8WzPP61nyY1D4dyYJyATDghpo5nEi3eC6p4U/iWwulkHj2LU7LB3vGbCE0JeeQ88RqevUj4ld66vqV8I9i4paBPzzUn5IK51fd93+/QspMRIW3wEl7q+UvJ93W/9PtDtIxn6mUdCk1Ncnetd36hwu+3b/d9sUkQ8T/wQ1zMjRvEZXPH6ek2j5qdyG9pMVN1/Gte7vn2dN3I7PBWn/vQrnuV61zceZ/w5Rx5tzBbjFZCGqvZPpa4v4He8JSG/+ZO7uDB8Hev6TpC9SwraNHx1Uj6Iur7An4cU3f/N/v78LDPxfr5neTzLJqf5Ovz6ivhAxmXRe8WmhtPQ3AUe/s2DO/OPQ1vznrN8CNPrq/JT4PstVYQKUcSvCkLwKPz3KTULSIzoVvc2jw3z0Sa8Q9DbDHpx61ojDbXNKab1E4/TmcUMfDkH1xeeTyGKwTWUDXSS0KScSKUsSIFbMlhAR91Lb2psPGEVmVp2Yj5WpZ2CsEZZ2JEJ2zVRrFlwniJBVzSVeb6+0nwWUSnS2sGQNJWgDMS/jZWkICcIMNKmQSxTBCS10RM+TuNNt35M7qiy70IMXEWLXM2Z6/tZxO3Q7q/4cb5E0HgH4sbdf9lWnyWE/TYMIbf55XGThtgSgO1gnEURpsYditmNNIU7GOYv7iFXM9f4xxX8lL//FcVF+KtFuwFV98Vl2Lju03TtUwF/3Pln3ls//GgZo+eWE2HrGq/v9VUvneFuvzvZowg9u9o/ACWG1/f1fWxFV6iv0kwnu0xblUx4Ot5f9/16zoQta7y81xeNGebmCf+y8097sUd+Gud/BFN1T8lANvDtPRl638X9lw68doNPouqJUp+xVXWrs88ndbuJxLl01ISbW1HYY+4Ud4cK8aBVNytqqvSwxK3RP3jh30t94z+XQRwdueWXYELjB7Jb3VOFY++39HyDwieXpABxfYmxE3YuF2fDltUuLyzXpF7GvTs/Nf6Cx6W0GgF34tG0Ui4kv/j64g8huZ25vrnJ6mG84X7PWfDC5wY3h9g6F/2uabBz7XqSF4hENIQJjVv3mRKdWhc1+QWguMmIoZ5WpFDjyZIV3ODo+pKI60tIL2pMaqPtsexQ9/9U50zIFvmDj1tOijjJskY6sMpyL3R+Ph1OeC5sSdOlYbm+bGpZMdtkoDb83Mgr9clxERqDDd3i0Vhc/HIZ2UalE/he9vbLfyajURuFcRiu48N/JHve7yUHjVJ8Evpd26Pre3yRD9ij7if1XnX/UXzC9d3lfm954L+OUDX/ecQ1Tb8X4VpsWvc3mw7JkGfBuc+4E372FQ+IclftokVPbFv3N5vOE4Ly7p7w+Psa/WYHsosX5yTK/LoFr2xU9/hhzZ/bP59OEzMqaPFR08vitNj1jXK/eOFvUPc5JV73bM7Vs/l7WZySfH3RZuWivFr3sX3JBOrekiKPM1BEGPaUo7Kec85Ld33zH75fmpfrnr+j909Bf75fg705ihPSXV/xfQKbPd9DbjRdcTLeVPH8DKDqKgbjHkz1eqFyRjwrk+mG5976Bj+Zb2Czy5+7zoetK60PT4EbL3jpdNGvub7gzqIowll+sOyZKA9WVZR+ls7OffueSchi+hVtcIPOSemne7D/Mc+Maeln4I2r9/XJd8GWlZdHyRte6eEWhs4pd2Ygwp96pOvbj5vOwx7xTkOJu0HmQQcLz3VzvyjRBBs/mLTT0blwuvby6XtPLit3MYVbEdZFbZFSAzDdz4q3jQJhkGmeLnIWhsuj3WBDul8WIm2janvASX6NarztnqV1ZFv7aZwO+NlU6WGJW0OiaRA3SQdM7RHxnghDqGa9eZiNMwnM7V4d0Pfbt+75XP35gC9HGusXtmjJBo2d/EmzzEjrpL5d5CSMV8d5YI94o3G1l4apKY4XPC6l1Qi4E49mKklAy61KiyWpTVZb3Nf3s4B3SFrGvVCsoBK73u+Je+uSlhtdlzV4aWMkp/kjDo3b0BJkeqwLnQJbU7e2pu4FaNJS00vD1BT3F4DiJiOGelqRQo0nSyhqDntRY9IiaIdoKPWLZiAnaMD7TTruW/f2idSeV73R+DLdpe4Q6CXC/egacQ6z4rbBPpGd/yTYmrq18W5kP2ndLMWwRvwsoCnh167ySj1yXITGYEO3eDQWh99tEqm1rtBEVWmLZLPxi9FBPu3njdoSZal6wsIaa62Gve/3G+KbLs7Fwutyqut3obovis3Ys+7lc2nb93jd8YtN2Pt+v/AjUOVDqu6LTdi57rVOu7u+fQro54EKKIjCATvTmUXxHPvW/WyZoqyhE9CkTQG3g9Yqiic5ou7Z6xFRYLmqQRWZgaso1vOeuu8eV+RBhoU/x0DCDrcrSkSK4iX2rftNkGon1CyK19mh7oviElTdF9/I1g8mhjyZLHo8qWeY4oOgckZFNw/n/KiOx3V9amfBXaFLDIeIorgYXMyqNqhTRDShwsyhorgMs3Wb61qA5v1zXPWiuAx4fhFFBGCvuS0AySb7WMJCUxRFURRFcQzxKDJ+JomHlmVQV0athsVzFMXuPKpGFD70zPy4NhLW/IiieDdWjXqTptY1LXlq5efxFkRAXdaPG1E4Iril/ZIfmvmL4v1E8Wk1apMklW5n0yvZaERhQnF3NFktisOIEmzr0vwsuYCTX17JBp3CrR2p0bYoDoWfOuTBI0Q0pqKASWOfPLiosBnQuq1Selg/72BS/UVRFEVRFO9DHz8eP4Y86FjPMcWVWFyu0jGaljl/UZwTFKt/FxpafwOHO5omHP6iuAJWrJBWvyYT4Wr9wpy/KM6JFSuk1e+ghC30IFgU54cfZ7hcVTZNU8Zsi8PcbXhqF0VRFEVRHM3MY8sUdOiff4w5f1GcksXVKh2jaZnzF8U5QbHGN62u9ffvMK1rhqyuf1GcGKtWSGmthi0EzGq9ho0pikvQlrO04xpOHabYuKK4Avw4w+WqsmmaMmZb3Qi04Un/oiiKYlPqHlt8JVX4xTdSdV98I1X3xTdSdV98I1X3xTdSdV8URfH5/PnzP7TBk7TuGUzmAAAAAElFTkSuQmCC" alt="" /> 

  咦!一看字节码才知道,我们的一行new的代码,对应的字节码原来要做这么多操作!我们逐一来分析一下。

一、new指令

1、检查、加载相应类

  JVM遇到new指令时,先检查指令参数(上面字节码中的#2)是否能在常量池中定位到一个类的符号引用(上面最终定位到常量池中的com/test/entity/People):

  1)、如果能定位到,检查这个符号引用代表的类是否已被加载、解析和初始化过;

  2)、如果不能定位到,或没有检查到,就先执行相应的类加载过程;

  具体类的加载、解析、初始化的过程大家可以去查找JVM类加载机制相关资料,这里就不展开啦!我们需要知道的是这一步保证了在方法区中,存在要创建实例对象的类对象

2、空间分配

  咱们到了适婚年龄,也就该找个对象了吧!你看上了一个姑娘,长得楚楚动人,就跑去跟他妈说:“我要一个对象,把你女儿嫁给我吧!”。她妈妈倒是十分爽快:“好啊,我女儿总得有个地方住吧,小伙子你有房吗?”。这时候场面一度十分尴尬,心里嘀咕着“要是国家能分配房子就好了!”。这在当前社会显然不现实,毕竟咱们还没进入共产主义社会!然而在JVM王国里,对象住的“房子”却是“国家”统一分配的。国家集中圈了一大块“地”,谁家要娶“媳妇”,就给他家分配一块“地”,“媳妇”胖点呢,地就大一点,“媳妇”瘦一点呢,“地”就小一点。在这里,你一个人可以同时拥有多个对象,在这里,多个人可以拥有同一个对象。所以这里的老百姓安居乐业、这里一片祥和……当然,由于这块“地”大小有限,而你又同时拥有很多对象,还有其他人也要娶对象,所以那些不用了的对象的“地”国家就会进行统一征收(当然这里不会给补贴,毕竟是免费分配的~)以继续分给其他人用。

  上面扯了这么多,相信你已经知道“你”就代表着一个线程,“国家”指的是JVM,“国家”圈的一块“地”就是堆空间,你娶的“对象”就是实例对象,“国家”分配地的动作就是内存分配,而国家征收的动作就是垃圾回收。

  由于要找对象的人太多了,所以分配的操作也很频繁,那么摆在“国家”的问题就来了:怎么合理分配?怎么最大限度的提高空间利用率?怎么提高分配效率?不用了的空间怎么回收?怎么知道哪些空间不用了?上面很多问题都需要结合后面的垃圾回收相关的内容来讨论,这里只讨论分配内存的方式。

  一个对象需要占用多大的内存?这个问题其实在类加载完成后就已经确定啦!JVM可以通过普通java对象的类元信息确定对象大小。为对象分配内存相当与把一块确定大小的内存从java堆中划分出来。那么问题来了,这么大的一块堆空间摆在JVM的面前,JVM该划哪一块空间来分配内存呢?随机找一块空间分配算了?or紧挨着之前分配的空间后面进行分配?这里需要说到的是两种分配方式:

  1)、 指针碰撞
  如果Java堆是绝对规整的:一边是用过的内存,一边是空闲的内存,中间一个指针作为边界指示器,分配内存只需向空闲那边移动指针,这种分配方式称为"指针碰撞"(Bump the Pointer)。这里有个条件就是“绝对规整”,类似下图,左边全是被绿过了的,右边则全是等着被绿的。新分配对象时候就是多绿了一块,边界指示器向后移动!
       

  2)、 空闲列表
  如果Java堆不是规整的:用过的和空闲的内存相互交错。需要维护一个列表,记录哪些内存可用。分配内存时查表找到一个足够大的内存,并更新列表,这种分配方式称为"空闲列表"(Free List)。类似下图,好好的一块内存被绿得乱七八糟,用上面指针碰撞的方式是碰不动了!所以就用一个小本本记着哪里有多大的空闲空间可以绿!当然下图的地址编号是虚拟的,空闲列表的样子也是我意淫出来的,表达的意思你懂就行! 
      

  我们能看到,导致这两种方式的差异主要取决于java堆是否规整,而java堆是否规整又是由jvm采用的垃圾收集器是否带有压缩功能决定的。使用Serial、ParNew等带Compact过程的收集器时,JVM采用指针碰撞方式分配内存。而使用CMS这种基于标记-清除(Mark-Sweep)算法的收集器时,采用空闲列表方式。(下篇文章会具体介绍不同的垃圾收集器)

  不管是指针碰撞还是空闲列表,都会存在同一个问题,那就是在多线程的场景下的线程安全问题。多个线程同时在new的时候把对象分配到同一块内存了咋办,不得干起来么!于是jvm采用了两种方案来解决:

  1)、 同步处理:JVM采用CAS(Compare and Swap)机制加上失败重试的方式,保证更新操作的原子性。CAS机制是一种轻量级锁机制,后续在聊多线程的时候再讲!

  2)、 本地线程分配缓冲区:把分配的内存按照不同的线程划分在不同的空间进行,每个线程在java堆区预先分配一小块内存,称为本地线程分配缓冲区(Thread Local Allocation Buffer)。哪个线程需要分配就从哪个线程的TLAB上分配,只有在TLAB用完需要分配新的TLAB的时候才需要做同步处理(通过上一点中的CAS机制)。

3、对象初始化

  内存分配完后,就需要初始化实例对象了,虚拟机需要将分配到的内存空间中的数据类型都初始化为零值(不包括对象头,如果是使用TLAB,初始化0值的操作提前至分配TLAB时)。接下来虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息,这些信息都存放在对象的对象头中。做完以上以后,从虚拟机视角来看,一个新的对象已经产生了!

4、返回地址

  JVM完成对象内存的分配及对象初始化之后,会返回对象的地址,并且压入操作数的栈顶,供后续操作!

二、dup指令

  dup命令没猜错的话是duplicate的简写。在讨论dup命令前,我们先看一个简单的例子

public static void main (String[] args){
int a;
int b = a = 88; }

  我们看看对应的字节码

public static void main(java.lang.String[]);
Code:
0: bipush 88
2: dup
3: istore_1
4: istore_2
5: return

  由于88这个值在一条语句中需要重复赋给两个变量,所以使用dup指令对栈顶的值进行了复制,且压入栈顶。我们在new对象的时候,new指令后面都会紧跟dup指令!然后是invokespecial和astore指令,相信聪明的你应该想到invokespecial和astore指令都会需要从栈顶弹出值来执行!在执行完dup指令后,操作数栈栈顶就有两个指向该对象实例内存的reference数据,如果<init>方法有参数,还需要把参数加载到操作栈。

三、invokespecial指令

  invokespecial指令调用对象实例方法<init>,通过符号引用#3定位到的是People对象的实例方法<init>。这时候操作数栈栈顶值(指向对象实例的内存reference)会被弹出(如果<init>方法有参数,参数也会出栈)。执行<init>方法会在java虚拟机栈中创建<init>方法的栈帧(相关栈和栈帧的介绍看上一篇文章),并且把出栈的数据放入栈帧的局部变量表中。变量表中指向对象实例的内存reference就是我们经常用到的this,表示对该对象实例进行操作!执行完该指令后,一个完整的对象就创建完成啦!

四、astore指令

  astore依然需要弹出栈顶值,然后存储到编号为1的变量中供后续使用。至此一个完整的对象已经创建且返回对象内存引用给本地变量存储了。

对象的访问定位

  我们上面已经把对象创建的问题解决了,同时我们也都知道,引用类型的变量存储的是**对象的引用**!那这个引用类型数据怎么定位到堆中的对象呢?目前主流的对象访问方式有两种:

1、使用句柄

  JVM在堆区划分一块内存作为句柄池,引用类型变量中存储就是对象的句柄地址。对象句柄包含两个地址(如下图):
  1、在堆中分配的对象实例数据的地址。
  2、这个对象类型数据地址。
      

2、使用直接指针

  引用类型变量中存储就是在堆中分配的对象实例数据的地址。
      

  句柄池的方式会在句柄池中存放类型对象的相关信息,而直接访问的方式会把类型对象的信息放入实例对象的对象头中(我们知道对象头包含“指向对象类型数据的指针”,其实这并不是必须的,我们常用的HotSpot虚拟机采用的是直接指针的方式,所以对象头中会包含“指向对象类型数据的指针”,如果某类虚拟机采用的是句柄的方式访问对象,那可能就不需要在头部存储这个指针了)。这两种方式都互有优缺点:

  1)、 句柄方式访问对象时,多一次指针定位的时间开销。但是对象移动时(垃圾回收时常见的动作),栈上的变量的引用不需要修改,只需改变句柄中实例数据指针。

  2)、 直接指针对象相对句柄方式访问节省了一次指针定位的时间开销,性能更好。如果对象访问非常频繁,提升会更明显!但是在对象移动时,栈上的变量的引用也需要变化。

你必须了解的java内存管理机制(二)-内存分配的更多相关文章

  1. Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches Slab内存管理机制 SLUB内存管理机制

    Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches   Slab内存管理机制 SLUB内存管理机制 http://w ...

  2. 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法

    垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...

  3. Java的内存管理机制之内存区域划分

    各位,好久不见.先做个预告,由于最近主要在做Java服务端开发,最近一段时间会更新Java服务端开发相关的一些知识,包括但不限于一些读书笔记.框架的学习笔记.和最近一段时间的思考和沉淀.先从Java虚 ...

  4. 分布式缓存系统 Memcached 内存管理机制

    在前面slab数据存储部分分析了Memecached中记录数据的具体存储机制,从中可以看到所采用的内存管理机制——slab内存管理,这也正是linux所采用的内存高效管理机制,对于Memchached ...

  5. Python内存管理机制-《源码解析》

    Python内存管理机制 Python 内存管理分层架构 /* An object allocator for Python. Here is an introduction to the layer ...

  6. 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配

    垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...

  7. java内存管理机制

    JAVA 内存管理总结 1. java是如何管理内存的 Java的内存管理就是对象的分配和释放问题.(两部分) 分配 :内存的分配是由程序完成的,程序员需要通过关键字new 为每个对象申请内存空间 ( ...

  8. Java虚拟机内存管理机制

    自动内存管理机制 Java虚拟机(JVM)在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区 ...

  9. 浅析java内存管理机制

    内存管理是计算机编程中的一个重要问题,一般来说,内存管理主要包括内存分配和内存回收两个部分.不同的编程语言有不同的内存管理机制,本文在对比C++和Java语言内存管理机制的不同的基础上,浅析java中 ...

  10. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

随机推荐

  1. 刷题总结——维护数列(NOI2005 bzoj1500 splay)

    题目: 题目背景 NOI2005 DAY1 T2 题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏中的下划线‘_’表示实际输入文件中的空格)

  2. Element 'plugin' cannot have character [children], because the type's content type is element-only

    原因是你复制的时候,带了一些特殊符号. 解决方案: 将那一串代码复制到notpad++ 或者文本上面,再复制到你的编译器里面,就可以解决问题了

  3. canvas 转化为 img

    ]; var image = new Image(); image.src = c.toDataURL("image/png"); $("#qrcode canvas&q ...

  4. 巧克力(zoj 1363)

    2100年,ACM牌巧克力将风靡全球. “绿的,橘红的,棕色的,红的…”,彩色的糖衣可能是ACM巧克力最吸引人的地方.你一共见过多少种颜色?现在,据说ACM公司从一个24种颜色的调色板中选择颜色来装饰 ...

  5. [深入学习C#]C#实现多线程的方式:Task——任务

    简介 .NET 4包含新名称空间System.Threading.Tasks,它 包含的类抽象出了线程功能. 在后台使用ThreadPool. 任务表示应完成的某个单元的工作. 这个单元的工作可以在单 ...

  6. LeetCode OJ--Binary Tree Level Order Traversal II

    http://oj.leetcode.com/problems/binary-tree-level-order-traversal-ii/ 树的层序遍历,和上一道题相比,对结果做一个顺序调整 reve ...

  7. SqlHelper类-全面

    // ===============================================================================// Microsoft Data ...

  8. AC日记——[SDOI2015]星际战争 洛谷 P3324

    题目描述 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战. 在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai.当一个巨型机器人的装甲值 ...

  9. HTTP状态码之200和304

    HTTP状态码之200和304   HTTP状态码(HTTP Status Code)是一种表示网页服务器响应状态的三位数字编码.通过这些数字,可以简化状态的表达.状态码有几十种,其中首位数字为1-5 ...

  10. mac下安装pyQt4

    1.首先安装QT,同时要有gcc 2.然后就是先安装sip,然后安装pyqt4 python configure.py -q /usr/bin/qmake-4.8 -d /Library/Python ...