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 执行的操作 )(代码片段