从C语言常量来思考Java语言的常量,Java的垃圾回收

声明:这是我自己的思考,不一定准确

字符串常量

首先我们要知道,在c语言中,也是字符串常量这种东西存在的,我们来看看他的存在形式

首先我们要知道,C语言有三种方式来定义字符串,但是只有其中的一种方式会以常量的形式存在,就是下面这种

char* s = "hello world";

字符串"hello world"位于只读数据区(段), 也就是大家说的.rodata 这是一个储存空间, 不是堆也不是栈.并且是在整个程序的生存周期都是存在的, 在栈上为变量c分配空间, 并给c复制为字符串"fghjxsdgbc"的地址,然后在函数调用结束后, 这个栈上的空间会被回收,但是字符串常量本身并不会被回收,而且这段内存是只读的。
也就是说,这段空间是在程序开始运行的时候就已经申请,对应到JVM中就是JVM一启动的时候,其内部的所有常量应该也就是确定的了。

那么Java中的常量池是怎么回事?
JVM常量池,只是JVM程序中的一个数据结构,其内部存储的常量,应该是随着Class的加载和卸载而发生变化的,这一点与C语言有很大的不同。
加载一个Class肯定是在JVM这个程序已经启动了之后才会进行的,这也可以确定,Java中的字符串常量肯定与C语言中的字符串常量是不一样的。JVM只是限制了我们在java层面无法取修改这个字符串常量,但是在JVM中他可能并不能算一个真正的常量。
在JVM中,即使是字符串常量,如果没有被引用,其还是会被垃圾回收器给回收的。例如一个字符串“abc”当前在常量池中,但是当前系统中没有任何一个String对象引用常量池中的“abc”常量,也没有其他地方引用,而且必要的话,这个“abc”会被系统清理出常量池。常量池中的其他符号引用(类,方法,字段)也是如此。
不知道能不能感受到这种区别所在。

垃圾回收

我们知道Java是有垃圾回收机制的,而且垃圾机制中有一种算法叫做标记整理算法,这种一开始我们很懵的,整理?怎么个整理法,操作系统好像没有这种API。
怎么把变量在内存中移动位置?而且是要移动到指定位置。

-Xms这个虚拟机参数,我想大家多少见多,设定程序启动时占用内存大小。由此就大概能看出来JAVA中的垃圾回收机制和标记整理算法是怎么回事了。我们设定了值,JVM一开始启动的时候,就向操作系统申请一块指定大小的内存(当然操作系统不会一次性分配这么多物理内存,毕竟是虚拟内存。可能是用malloc函数进行申请),将内存的首地址保留着。这块内存,就是整个JVM可以进行操作的内存了,JVM想怎么在这块内存上操作都可以。这时候的JVM就可以看作一个简单的操作系统,然后JVM就可以建立一个数据结构来管理这块内存了,负责空闲空间的管理,给变量在这块内存上分配变量,回收变量所占的内存等等(感觉就像一个小的操作系统啊)。这种回收,并不是交换给操作系统,而仅仅是在自己的数据结构上进行了标记。标记整理算法也就能轻易的实现了,毕竟有了头指针和大小,想在内存的哪个位置操作都可以

当然上面这些都是我的猜想,但是我没有查询到相关资料,当然可以去阅读Open-JDK来看看到底是不是这么回事,大概也八九不离十。

由下面的垃圾回收机制设想,同时也能说明上面常量池是怎么回事,说白了都是JVM对自己程序内部的数据结构的管理。

发布了162 篇原创文章 · 获赞 44 · 访问量 8820

猜你喜欢

转载自blog.csdn.net/P19777/article/details/104072270