Java的内存分配

Jvm中将内存分为:寄存器,栈,堆,方法区(静态域,常量池)

1. 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制,可以不理会

2. 栈: (stacksegment)

       2.1:存取速度仅次于寄存器的存储区,速度快,先进后出(first in last out)

       2.2:存放8大基本类型数据(int, short, long, byte, float, double, boolean, char)和对象引用,(仅存放引用,不存放数据)

             存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中)

             数据可以共享(详见备注例子)

       2.3: 存放数据大小确定,生存期必须是确定的,缺乏灵活性

              对于每个线程都有一个栈,每个栈中的数据都是私有的,不能访问别的栈中对象

       备注例子:

             int a = 3;
            int b = 3;

            首先栈中创建变量为a的引用,查找栈中是否有3,有则把a指向该地址,否则就开辟一个地址存放3 (3为基本数据类型,存放在常量池中,a为3的引用存放在栈中);

            那么b的引用就直接指向了a中所指向的地址3;

            如果将 b=3 改为 b=4 并不会影响a的值,会在栈中查找是否有4的地址,有则将b的引用指向4的地址,没有就开辟一个地址存放4

           这里的引用与java中类的引用不同

         2.4: 对于String型数据,如果是编译期生成如 String a = "123"; a 在栈中 ,123 在常量池中, 

                如果是在运行期生成String a = new String("123");a在栈中,123会在常量池中生成(如果常量池中不存在),并在堆内存中生成常量池的"123"的拷贝对象"123";

             备注:这里new String("123")生成了两个对象(如果常量池中不存在),否则就是生成一个对象

         2.5: 生命周期:由编译器自动分配释放,存放函数的参数值,局部变量的值等,具体方法执行结束之后,系统自动释放JVM内存资源

3.堆:   (heapsegment)

          优势是:可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。

          缺点是:由于要在运行时动态分配内存,存取速度较慢。

          new的对象都存在这里

          多线程共享该堆

          生命周期 : 一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收,或由GC回收

 

4.方法区:方法区是系统分配的一个内存逻辑区域,是JVM在装载类文件时,用于存储类型信息的(类的描述信息)。

4.1.常量池:      

         常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。

         除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用

         比如:

                类和接口的全限定名;

                字段的名称和描述符;

                方法和名称和描述符。

         final的具体规则
              ·final标记的类不能被继承
              ·final标记的方法不能被子类重写
              ·final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次

         在这里要详细的说下final(举例):

                   String s1="我爱LOL";               //s1指向"我爱LOL"

                       String s2="我爱"+"LOL";          //只是将s2指向了"我爱LOL"

                       System.out.println(s1==s2);    //true

                       String str1="我爱";  

                       String str2="LOL";            

                       String s3=str1+str2;              //str1,str2为变量,不执行宏替换,编译时无法使s3指向常量池,所以会生成新的对象     

                       System.out.println(s1==s3);    //false

                       这里将str1,str2用final修饰,就使的 s1== s3 为true

                       final修饰的变量实质上就是一个“宏变量”,编译器会把程序中所有用到该变量的地方替换成该变量的值

4.2.静态域:(datasegment)

         存放静态成员(static定义的)

         生命周期: 存放全局变量,静态变量和字符串常量,不释放

 

 对于jvm内存分析完,我们来将内存合理的用到实际的开发中来: 开发环境的合理化内存分配

在开发环境中内存不如jvm中这么详细,只分为 堆 和 非堆 两个内存区, 因此我们设置的时候就很简单了,设置堆的最大最小值,设置非堆的最大最小值

      详解 堆 ,非堆:

              堆:指的是运行时的数据区域内存,相当于jvm中的堆,而在jvm中的堆是存new 数据和数组数据的,由此可见这是留给我们开发人员用的

            非堆:指的是编译时的数据区,相当于jvm中的方法区,存放静态方法,常量,构造函数,字段等编译后的代码,由此可见这是留给jvm自己用的

      如何设置其大小:

                堆内存:默认大小为范围为 物理内存的 1/64  - 1/4;

                          默认剩余内存小于最小内存40%时自动扩充到最大内存 , 剩余 内存大于最大内存的70%自动缩小的最小内存

                          最小内存由 -Xms 设置,最大内存由-Xmx 设置

                非堆内存(也叫持久区):默认范围也是 物理内存的 1/64 - 1/4;

                          最小内存 -XX:PermSize设置,最大内存 -XX:MaxPermSize 设置

                由于存在多线程,对每个线程的栈大小也有设定:jdk5.0以后默认是1M,以前默认256k

                           由-Xss来设置

      设置例子:  -server -Xss256k -Xms512m -Xmx512m -XX:PermSize=256m -XX:MaxPermSize=256m

                     -server是配置服务器的意思,一般用来在tomcat中配置

转载于:https://www.cnblogs.com/yiyongyao/p/4498653.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值