java创建对象内存分配空间及其原理一

2/10/2017来源:ASP.NET技巧人气:328

          一直想写关于java对象的文章,一直拖着就等到了现在。其实,当你真正走上程序员这条道路的正轨时,代码对于我们来说,已经不再是问题了。但是,假如我问你原理,你真的能知道其一二吗?

         网上关于java的文章琳琅满目,但真的讲到原理这东西,很多都是晦涩难懂,有点小复杂。所以,我将用通俗易懂的语言去讲解一些原理性的东西。

         话不多说,进入正题。

         我们学习java必定知道创建对象,然后我们通过这个对象拿变量,拿方法。但是,这里面的java虚拟机到底是怎么准确拿到这些东西的呢?首先,我们要先搞明白,关于计算机,我们玩的都是地址,地址很重要。例如,C语言,我们玩的就是指针,讲俗点,指针就是地址。首先,jvm为我们分配三块重要的内存空间,栈内存,堆内存以及方法区。这里我只讲解方法区。方法区,也就是入口,所有要用到的东西,都要现在这里提前加载完。我先举创建一个对象的情况,如Person p = new Person( )。当我们编写完java文件,要编译成.class文件,然后 .class文件加载进方法区。每个程序都有一个入口函数,就讲main方法吧。当.class文件加载进方法区的时候,main主函数就要压进栈内存了。当main主函数压进栈内存后,jvm就会去找引用变量p,但是p是什么东西呢?不知道。恰好,引用变量前,已经声明是person了。所以jvm会将person类加载进方法区,那现在好办事了。我们通过new Person(),就到堆内存了。在堆内存通过new开辟一片空间,但你要明确,这片空间本来就是有地址的。内存中只是提供一块地方给你用,不一定代表他就是是无名地哦。我们知道,类是属性和行为的集合,属性包括有基本数据类型,他们都有默认值,只要在我们没有在使用前赋值,你要记住,他们都是有默认值的。继续,通过new之后,堆内存开辟的空间的地址就指向了引用变量,所以,现在我们就可以去使用该对象的成员变量和成员方法。

        整个对象创建过程我们已经很清楚了。但是这只是引用了堆内存空间地址而已,我们还要使用该对象成员方法那原理又是怎样呢?上述我们知道,我们引用变量拿到了对象的地址,所以我们要调用对象的方法当然也是通过该地址。不过,我们现在是在栈内存中操作。我们在栈内存也开辟一片空间,我们俗称方法压进栈,此方法就是该对象的方法。当此方法调用完后,就会被释放掉,俗称弹栈,即它会弹出栈内存,没用了,下次再使用该方法时,再会执行进栈和弹栈的操作。

      至此,我们便知道了创建对象、使用成员变量和成员方法的原理了,但是我们不可能对象地址一直指向引用变量。是的,所以在整个应用程序执行完毕后,主函数方法也会弹出栈,此时的引用指向也会想风筝断了弦一样,没用人牵着它。此时,有个重要的人物要出现------垃圾回收(GC)。jvm自己有垃圾回收机制,它会不断在堆内存中巡视,当它发现使用过的对象地址没有被引用时,它就会将此内存回收掉,避免资源的浪费。java虚拟机还是很方便的。如果是C语言,你的老师可能会经常提醒你,记得回收删除不必要的引用。但是,jvm就没这个问题,我们只需要做我们该做的事情就ok了。

     同理,当我们创建两个对象的时候,其原理一模一样。就是同样进行上述操作。主要要区别的是,我们创建两个相同对象方法区该怎么加载呢?就讲上述的Person类,我们方法区只去加载一次就可以用多次,不会像堆内存那样,不断开辟空间去引用地址。