java内存分析

Posted tubewang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java内存分析相关的知识,希望对你有一定的参考价值。

1、JVM的概述

  • 在一台计算机上由软件或硬件模拟的计算机。Java虚拟机(JVM)读取并处理经编译过的平台无关的字节码class文件。
  • Java编译器针对Java虚拟机产生class文件,因此是独立于平台的。
  • Java解释器负责将Java虚拟机的代码在特定的平台上运行。

2、JVM 的平台相关性

  • Java 源代码和字节码是与机器无关的;
  • JVM 是与机器相关的 ;
  • 装有不同操作系统的机器上,需要有专门为该操作系统开发的 JVM

 注意:jvm的上层是跨平台的,而jvm是不跨平台的。

3、 Java语言程序解释执行环境

      技术图片

 操作系统就是封装了硬件的“虚拟机”——第一次封装

    JVM虚拟机——第二次封装

 技术图片

接收字节码文件——>调用类加载器,把字节码文件加载到虚内存的方法区的类代码区,创建一个和类相关的反射对象——>字节码验证:验证是否有非法的内存访问——>(interpreter)解释成相应的机器语言

4、Java的垃圾回收机制(GC

  • 不再使用的内存空间应回收----垃圾收集。
  • 在C/C++ 等语言中,由程序员负责回收无用内存。
  • 它提供一种系统级线程跟踪存储空间的分配情况。
  • 垃圾收集在Java程序运行过程中自动进行,程序员无法精确控制和干预。

 5、几个常用的命令

  • javac:Java编译器,用来将java程序编译成Bytecode。
  • java:Java解释器,执行已经转换成Bytecode的java应用程序。
  • javap:反编译,将类文件还原回方法和变量。
  • javadoc:文档生成器,创建html文件。

6、Applet

 Java Applet(小应用程序):不是一个完整的应用程序,而是框架程序中的一个模块,所以只能在WWW 浏览器环境下运行。

Java Applet 工作原理:

       技术图片

Applet的缺点不安全,因为它只能编译成字节码,嵌入到html文件,用户访问html时候不知道里面有applet,而applet里面可能被非法利用包含黑客病毒,所以不安全。

Applet只做了解。

【拓展】

1、jdk,jre,jvm的区别和联系:jdk是java的开发工具包,jre是java的运行环境,jvm则是让java能够在任何平台运行的虚拟机。其中关系是jdk包含jre和tools(开发工具类),而jre包含类库和jvm。

2、主方法和主类:

1.主方法是运行的入口,是虚拟机的入口,它和运行指令java.有关;
2.主类是编译的入口,是编译器的入口,他和编译指令javac 有关。

 为什么有主类的java程序中可以没有主方法?  

           因为有了主类就会被正常编译,而主方法和执行有关,他和编译是分开的。所以他能正常。

 为什么有主方法的类可以不是主类,也就是说带有public的类里可以不写主方法?

    比如javabean,原理就是通过tomcat反射进行

3、HelloWolrd内存空间的分配详解: 

Java内存分配:
1、栈(Stack):主要用来存放局部变量
2、堆(Heap):主要用来存放new关键词创建的对象。

  • 堆中的数据具有默认值:
    • a)如果是整数,默认是0;
    • b)如果是浮点数,默认是0.0;
    • c)如果是字符,默认是“\\u0000”(Unicode写法)。
    • d)如果是布尔值,默认为false。
    • e)如果是引用类型(包含字符串),默认为null(空常量)。

3、方法区(Method Area):包括类代码区、共享代码段、常量池,静态数据区等。
4、本地方法区(Native Method Area):与操作系统相关。
5、寄存器(pc Register):与CPU相关,性能极高。

代码示例:

public class HelloWorld 
    /*
     * main函数写法的“三个帽子”详述:
     *        public:让虚拟机使用主方法
     *        static:告诉虚拟机如何找到主方法——通过类找主方法
     *        void:虚拟机不会处理返回值
     * */
    public static void main(String[] args) 
        String s; // 定义一个String类型的变量 s
        s = "Hello World."; // 定义字符串 s
        System.out.println(s.hashCode());
    
  

内存图:

   技术图片

说明:

1、

  字节码文件——HelloWorld.class、String[].class、String.class、System.class  4个

  对象——字符串空数组对象String[] args、3个流对象、一个常对象string   5

  方法——main主方法、println方法、toString()方法    3

  变量(基本上为局部)——args、s   2

2、

  标准字节输出流对象 System.out

  标准字节输入流对象System.in

  标准字节出错流对象System.err

3、分析从编译到执行到输出结果的过程:

  1.  先通过编译器(javac)编译HelloWorld.java文件,找到主类HelloWorld里面有多少个类(多个类中只有一个类可以被public修饰)就编译成多少个.class字节码文件

  2.然后通过虚拟机(JVM)解释含有主函数的.class文件(HelloWorld.class)。通过main()方法获得程序的入口,此时通过三个允许(static静态绑定类,用public确定方法,再用void确定不处理返回值)才可以进入并执行该程序。

  3.主方法在内存的栈区的开辟工作空间,开始main方法的时候会到标准类库调用String[] ,String , System标准字节输入输出流,Object等这几个类的字节码文件加载到方法区的类代码段中。

  4.在堆区创建一个空(String[ ])数组对象从栈区把args传过来到堆的空数组对象String[ ]中。

  5.因为String s 是成员变量所以在主方法的工作区间创建String类型的 s 变量。

  6.定义了一个”Hello world !”常量对象存放在方法区的常量值数据区并且会创建相应的toString()方法,栈区的s变量指向了 这个方法区的常量。

  7.最后执行输出语句输出其实是s的地址,但是s指向(存储)的是“Hello world !”常对象的地址,而且该常对象覆盖重写了父类的toString()方法,所以最后输出的结果是:Hello world !     

       技术图片

 

 

以上是关于java内存分析的主要内容,如果未能解决你的问题,请参考以下文章

变量的内存分析图

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

java 片段将重用以前膨胀的根视图,这可以节省内存。好可怜 ......

Java 垃圾回收 - 收集算法

任何可以找到内存泄漏java代码的java静态代码分析器?

大数据必学Java基础(三十四):面向对象内存分析