方法区----------运行时常量池(线程共享区)

运行时常量池

运行时常量池(Runtime Constant Pool)是方法区的一部分。 Class文件中除了有类的版
本、 字段、 方法、 接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于
存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常
量池中存放。
Java虚拟机对Class文件每一部分(自然也包括常量池)的格式都有严格规定,每一个字
节用于存储哪种数据都必须符合规范上的要求才会被虚拟机认可、 装载和执行,但对于运行
时常量池,Java虚拟机规范没有做任何细节的要求,不同的提供商实现的虚拟机可以按照自
己的需要来实现这个内存区域。 不过,一般来说,除了保存Class文件中描述的符号引用外,
还会把翻译出来的直接引用也存储在运行时常量池中[1]。
运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不
要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方
法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较
多的便是String类的intern()方法。
既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申
请到内存时会抛出OutOfMemoryError异常。

方法区----------运行时常量池(线程共享区)

第24行,创建的字符串,在程序运行时,会将“abc”放到方法区的运行时常量池中,再当25行创建s2时,会到常量池中去找有没有“abc”,然后将“abc”赋值给s2,所以29行输出为true。
第27行,使用new关键字创建字符串,会将“abc”放到Java堆中,所以30行,输出为false,他们分别在不同的存储区域,所有地址是不同的。
第31行,s3使用intern() 方法,这个方法是native方法,是将s3指向的“abc”放到常量池中,但是常量池中存在“abc”,所以s3,s1,s2指向的是同一个常量池中的“abc”。

直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规
范中定义的内存区域。 但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError
异常出现,所以我们放到这里一起讲解。


在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓
冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储
在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。 这样能在一些场景中显著
提高性能,因为避免了在Java堆和Native堆中来回复制数据。


显然,本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,肯定还是
会受到本机总内存(包括RAM以及SWAP区或者分页文件)大小以及处理器寻址空间的限
制。 服务器管理员在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略
直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),
从而导致动态扩展时出现OutOfMemoryError异常。

直接内存 说白了,就是    直接内存中存放的是Native函数库   间接扩大Java堆的大小的,在Java堆中有一个DirectByteBuffer对象可以直接去 直接内存 中拿数据使用。