`
jgnan
  • 浏览: 88760 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

每天简单JAVA教学:JVM的内存管理,static的用法

阅读更多
今天的主题是介绍static和final这两个指示器的用法。但是为了说明它们两个的具体作用之前,我觉得还是有必要先说说jvm的内存管理。

关于这部分,网上已经有很多不错的文章了,比如这个:
http://topic.csdn.net/u/20090602/10/bd9d4ba2-dbeb-49b3-8651-67c5de2b228a.html

官方的白皮书:
[url]https://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf
[/url]

而关于今天的主题,大家只需要关心官方版本的一句话就好,垃圾回收等内容大家可以有兴趣的就读一下:

在JVM里面,内存被划分为3个区间:Young,Old和Permanent。就是新生代,老生代及永生代。大部分的初始化都是在新生代内存进行的,然后存活时间较长的或者一部分大对象被保存到老生代。而那些便于JVM管理的不会去主动回收的对象,都保留在永生代。

而关于最后一个区间,官方的答案是一般关于类和方法的描述对象,以及类和对象本身,都会被保存到永生代里面!

所以。我们写的.java文件里面的每个class到了jvm里面就会变成一个单独的对象。这个我个人习惯叫类模版,因为它的确很像模版。然后我们要用的往往不是这个模版本身,而是基于这个模版产生的一份拷贝,也就是它的一个实例(instance)。所以,在上一个例子里面,我们需要使用new这个关键字,来在JVM的新生代生成一个Modifier对象的实例。()表示调用默认的Modifier的构造函数。构造函数往往会在创建实例的时候进行一些初始化动作,以使得每个创建的实例会代一些我们预期的初始参数。而且一个模版可以带有多个构造函数,构造函数也可以接受各种参数,例如:

package constructor;

public class ConstructorDemo {
    /**
     * 重载了默认不带参数的构造函数,初始化实例时会执行里面的命令
      */
    public ConstructorDemo()
    {
        System.out.println("I'm the default constructor!");
    }
	
    /**
     * 如果调用new ConstructorDemo(name)来构造实例,则控制台显示不同的内容
      * @param name
     */
    public ConstructorDemo(String name)
    {
        System.out.println("New instance with name : "+name);
    }
}


大家可以自己去用这两个构造函数来初始化实例试试有什么不同。

那么,大家就可以理解,其实class的内容,以及里面的方法,在JVM里面都有一段内存保存着其内容,但是其实并没有直接分配一段可执行的内存空间给它们。所以我们不能够直接调用没有加static的方法。而且由于自动内存管理机制,我们也很难保证同一个类模版的新实例固定在某个地址段里面。

但是static字段允许我们直接让类模版里面的某些方法或字段在直接在类模板的内存段里面划分出来。让这些static方法或者字段可以直接被外部直接访问永生代的一个固定地址来访问。因此,访问static的方法时,可以不创建某个类的实例而是直接通过类模版对象来访问:

package staticnfinal;

public class StaticDemo {
    public static void main(String[] args) {
        //调用static方法:
        StaticDemo.staticMethod();
        //调用非static方法
         StaticDemo demo = new StaticDemo();
        demo.notStaticMethod();
        /*
         * 通过实例来访问静态方法也是可以的,但是我们不推荐这种做法,
         * Eclipse也会有warning
         */
        demo.staticMethod();
    }
	
    public static void staticMethod()
    {
        System.out.println("I can be call without creating new instance");
    }
	
    public void notStaticMethod()
    {
        System.out.println("I must be call after creating new instance!");
    }
}


最后一个例子大家会发现通过实例也可以调用staticMethod,但是我们不推荐这种做法。

大家可能会问,加static和不加static有什么区别?什么时候应该加,什么时候不应该加?其实问题是这样的。static的方法或字段会占用永生代的内存,前面已经说过这段内存是不会主动去清空它的,所以jvm也是默认往里面放最常用的东西,如类模版对象,方法模版对象以及对它们的映射对象等。所以,如果我们要把方法或者字段定义为static,就一定要是那种会被经常访问到的东西,比如系统的全局变量啊,一些常用的工具方法等等。而不能乱用,因为用多了,应用的内存就会高居不下,因为动态内存少了,固定内存太多。

虽然每次要用方法要开个新的实例貌似更加麻烦及占内存,但是如果从长远来看,由于实例一旦没有被进一步调用就会被自动清理,所以这种方式会很省空间。而且在多线程的情况下,这种每个实例自己一个方法调用空间的做法,也会避免了一些同步问题。所以如果不是是非必要的话,大家还是少用static来生命对象为妙。

明天会介绍方法继承,重构及重载,还有final标识符。
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    Sun JVM原理与内存管理

    ### Sun JVM原理与内存管理 #### 一、Sun JDK 1.6 GC (Garbage Collector) Sun JDK 1.6 的垃圾收集器(GC)是其内存管理的关键组成部分,它负责自动地回收不再使用的对象所占用的内存。本文将详细介绍Sun JDK 1.6 GC...

    java虚拟机JVM详解ppt

    通过对Java虚拟机JVM的基本概念、架构以及内存管理机制的深入解析,我们可以更好地理解Java程序的执行过程。掌握JVM的工作原理有助于开发者编写更高效、更稳定的Java应用程序,并能有效地解决常见的内存溢出问题。

    java技术:java中static作用详解

    Java中的`static`关键字在编程中扮演着至关重要的角色,主要用在以下几个方面: 1. **静态变量(Static Variables)**: - 静态变量由类共享,而不是由类的实例(对象)单独拥有。这意味着所有实例共享同一份静态...

    JVM性能调优-JVM内存整理及GC回收.pdf

    这种方法简单但效率不高,且会导致内存碎片化。 2. **复制算法**:将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的...

    jvm内存溢出

    - **Java虚拟机栈(JVM Stack)**:描述的是Java方法执行的内存模型,每个方法被执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。如果线程请求的栈深度大于虚拟机所允许的深度,则会...

    Java的内存管理机制分析

    ### Java的内存管理机制分析 #### 一、Java内存区域划分 Java的内存管理机制将内存分为以下几个区域: 1. **栈(Stack)**: - 存储局部变量(如基本类型的变量和对象的引用)。 - 每个线程拥有一个独立的栈。 ...

    java 查看JVM中所有的线程的活动状况

    首先,Java提供了`java.lang.management.ThreadMXBean`接口,它是管理JVM线程的管理接口。通过这个接口,我们可以获取线程的各种信息,包括线程ID、线程名称、线程状态等。线程状态主要有以下几种: 1. 新建(NEW)...

    使用C++创建java虚拟机JVM,使用JNI调用java函数.zip

    本文将深入探讨如何使用C++创建Java虚拟机(JVM),并通过JNI来调用Java函数。这是一项技术性很强的任务,需要对C++编程、Java虚拟机的工作原理以及JNI接口有深入的理解。 首先,Java虚拟机(JVM)是Java平台的核心...

    java中带static关键字的程序内存分析

    理解`static`关键字对于深入理解Java程序的内存管理至关重要。在本文中,我们将详细探讨`static`关键字在Java程序内存分析中的应用。 首先,`static`关键字用于声明类变量或静态方法。类变量是属于类本身,而不是类...

    java-----static内存分析

    ### Java中的`static`关键字与内存管理分析 #### 一、`static`关键字的理解与应用场景 在Java中,`static`关键字主要用于修饰类中的成员变量和成员方法,使其成为类级别的成员。这意味着无论创建多少个该类的实例...

    Java Thread in JVM

    根据Java语言规范,`synchronized`修饰的方法有两种形式:静态(`static`)方法和实例方法。 - 静态方法的同步锁是该类的Class对象。这意味着所有对该类静态方法的同步访问都会锁定在同一把锁上。 - 实例方法的...

    Java中的Static块与静态方法

    在Java编程语言中,`static`关键字扮演着至关重要的角色,它被用于声明类成员(如变量、方法)为静态的。静态成员不依赖于任何特定的对象实例,而是与类本身绑定,这意味着无论该类有多少个实例,静态成员只会有一份...

    关于(java heap space)内存溢出的解决办法

    在Java编程中,"java heap space"内存溢出是一个常见的问题,它通常发生在应用程序尝试分配超过JVM堆内存限制的对象时。这个问题对于任何Java开发者来说都至关重要,因为如果不妥善处理,可能会导致程序崩溃。以下是...

    java中static作用

    static 是 Java 语言中一个关键字,表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态代码块。在 Java 语言中,没有全局变量的概念,但是可以使用 static 来实现类似于全局变量的效果。 ...

    JVM 38道面试题及答案.docx

    内存泄露:内存泄露是指一个不再被程序使用的对象或变量一直被占据在内存中。Java 中有垃圾回收机制,可以消除引用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么 GC 也可以回收它们。

    static在Java语言中的作用

    ### static在Java语言中的作用 ...`static`关键字在Java中用于定义静态属性和方法,有助于优化程序性能和资源管理。通过了解`static`的多种用途,开发者可以更好地设计高效、优雅的Java应用程序。

Global site tag (gtag.js) - Google Analytics