zoukankan      html  css  js  c++  java
  • JAVA的堆栈和内存、垃圾回收解说

    1.有关java健壮性特点的真相

    很多书上都说java健壮性的特点是因为java使用数组代替了c++的指针;c++最令人头痛的问题就是内存问题,java的健壮性使编程人员不用再考虑内存的问题;这种观点和想法是不对,java虽然有垃圾回收机制,不需要程序员去delete内存,但是在编码的时候还是应该考虑到内存的,尽量不要去浪费jvm的内存;这里就涉及到了java的堆栈问题。

    2.java堆栈的区别

      堆:存放类类型,用new建立,垃圾自动回收机制负责回收,速度慢

    1).堆是一个“运行时”数据区,类实例化对象是从堆上去分配空间的,也就是说堆上空间都是通过new指令建立的;

    2).与c++的区别就是java不需要显示的去释放堆,而是由垃圾回收机制负责,这是因为堆是动态分配内存大小的,即程序运行的时候分配;

    3).这也产生了一个问题,堆空间的数据内存读取比较慢。

        例:String str =new String(“yangkai”);

      栈:存放基本数据类型,速度快

    1).栈主要存放基本数据类型(byte、short、int、long、float、double、boolean、char)和对象句柄;

    2).数据可以共享;何为共享?这里说的共享不是程序员决定的而是由jvm来控制,指系统自动处理的方式,比如说:int a = 10;int b= 10;这里的a、b变量指向的栈上空间地址是同一个,这就是所谓的“数据共享”;jvm的处理逻辑:java虚拟机去处理int a = 10的时候先去栈上创建一个变量作为a的引用,然后去查栈去找有没有10的值,如果有就将a指向10,如果没有就把10存进来。

    3).相对于堆来说速度快;

    4).栈数据的大小与生存期是确定的,缺乏灵活性。

    例:int a = 0;

    3.实例化对象的方法

      比如说String这个类的实例可以由两种方法建立:

    String str = new String(“yangkai”);

    String str = “yangkai”;

       分析:这两个方式创建的额对象是不同的,依照咱们上面介绍的堆栈知识应该对这种String的实例有所了解了吧!第一种采用new方式的在堆上开辟空间没调用一次就会创建一个对象;第二种是现在栈上创建String对象的引用,然后存储“yangkai”再让str引用;下次再调用str,如果栈上有就不会再次创建了;所以一般比较String变量的时候都采用两种方式,equals()和“==”;一般“==”判断的是对象是否相等即是否是同一个对象;判断出来两个String对象相等了说明这个字符串是存放在栈的,数据是共享的,这两个字符串是同一个对象;而equals()判断两个对象的内容是否相等,比如判断堆上的字符串的内容只能通过equals()方法来判断,“==”判断的可能是false,因为每一个string在堆上都是以一个String对象存储的。

    4.如何控制内存,这里教你查看jvm内存的使用

    当前虚拟机的最大内存: Runtime.getRuntime().maxMemory();

    循环前虚拟机已占内存: Runtime.getRuntime().totalMemory();

       下面使用两个案例来监测jvm内存:

    package com.hudong.memory;
    /**
     *
     * @Title: MemoryTest.java
     * @Copyright: Copyright (c)2005
     * @Description: <br>
     * <br>
     *              测试java虚拟机的内存占用情况
    * @Created on 2014-1-21 上午11:40:35
     * @author杨凯
     */
    public class MemoryTest {
     
        /**
        * @param args
        */
        public static void main(String[]args) {
           testStringBuffer();
           // testString();
        }
     
        /**
        * 测试String实例对象的占用的内存
        */
        public static void testString() {
           String str = new String("abcdefghijklmn");
           int count = 0;
           System.out.println("当前虚拟机的最大内存:" + Runtime.getRuntime().maxMemory()/ 1024 / 1024 + "m------" + Runtime.getRuntime().maxMemory()+ "byte");
           System.out.println("循环前虚拟机已占内存:" + Runtime.getRuntime().totalMemory()/ 1024 / 1024 + "m====" + Runtime.getRuntime().totalMemory()+ "byte");
           while (true) {
               try {
                    str += str;
                    count++;
                } catch (Error e) {
                    System.out.println("循环次数:" + count);
                    System.out.println("字符串循环后的大小为:" + str.length() / 1024 / 1024 + "m-=-=-=" + str.length() + "byte");
                    System.out.println("循环前虚拟机已占内存:" + Runtime.getRuntime().totalMemory()/ 1024 / 1024 + "m====" + Runtime.getRuntime().totalMemory()+ "byte");
                    System.out.println("遇到错误:" + e);
                    break;
               }
           }
           /*
            * 运行结果:
            * 当前虚拟机的最大内存:793m------832438272byte
               循环前虚拟机已占内存:127m====133234688byte
               循环次数:23
               字符串循环后的大小为:112m-=-=-=117440512byte
               循环前虚拟机已占内存:642m====673669120byte
               遇到错误:java.lang.OutOfMemoryError: Java heap space
            */
        }
     
        /**
         * 测试StringBuffer实例对象的占用的内存
        */
        public static void testStringBuffer(){
           StringBuffer sb = new StringBuffer("abcdefghijklmn");
           int count = 0;
           System.out.println("当前虚拟机的最大内存:" + Runtime.getRuntime().maxMemory()/ 1024 / 1024 + "m------" + Runtime.getRuntime().maxMemory()+ "byte");
           System.out.println("循环前虚拟机已占内存:" + Runtime.getRuntime().totalMemory()/ 1024 / 1024 + "m====" + Runtime.getRuntime().totalMemory()+ "byte");
           while (true) {
               try {
                    sb.append(sb);
                    count++;
               } catch (Error e) {
                    System.out.println("循环次数:" + count);
                    System.out.println("字符串循环后的大小为:" + sb.length() / 1024 / 1024 + "m-=-=-=" + sb.length() + "byte");
                    System.out.println("循环前虚拟机已占内存:" + Runtime.getRuntime().totalMemory()/ 1024 / 1024 + "m====" + Runtime.getRuntime().totalMemory()+ "byte");
                    System.out.println("遇到错误:" + e);
                    break;
               }
           }
           /*
            * 运行结果:
            * 当前虚拟机的最大内存:793m------832438272byte
               循环前虚拟机已占内存:127m====133234688byte
               循环次数:23
               字符串循环后的大小为:112m-=-=-=117440512byte
               循环前虚拟机已占内存:539m====566108160byte
               遇到错误:java.lang.OutOfMemoryError: Java heap space
     
            */
        }
    }


       分析:以上两个程序用来说明String和StringBuffer两个占用内存的情况;其他资料上面介绍这两个类的使用的时候得出的结果是:Stringbuffer比String循环后得到的字符串字节大;而我在这测试的时候得到结果两个类得到的字符串大小是一样的,区别是耗费的额虚拟机的内存大小不一样,后者明显的比前者小。

      注:安装完jdk之后jvm默认的大小是63m,上面我测试的时候是将jvm的配置文件的xmx大小调大之后的。

  • 相关阅读:
    vTiger 5.2+ 语言包安装教程
    linux iconv方法的使用
    php XMLWriter类的简单示例
    DIV+CSS网站导航条
    php同步方案
    PHP区间分页
    phpcms2008添加上一篇下一篇的功能
    Yii框架整合Ucenter更新与增强
    Linux openSUSE / CentOS / Slackware / Gentoo
    project mail
  • 原文地址:https://www.cnblogs.com/yangkai-cn/p/4016693.html
Copyright © 2011-2022 走看看