最近的项目中,出现了内存和性能的问题,需要优化,所以趁着这个机会,把自己关于java虚拟机的东整理一下,不对的地方,欢迎指出。

数据类型,因为在java的优化的过程中,检测到的数据类型一般比较的基础,毕竟复杂的数据类型就是有基础的组合而来的。

Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,表示的是数据本身的值,是数据中的最基础的部分,一般包含:

byte,short,int,long,char,float,double,Boolean,returnAddress

其中的byte,short,int,long,char,float,double,Boolean 就不多说了,returnAddress 是会被Java虚拟机的jsr、ret和jsr_w指令所使用。return Address类型的值指向一条虚拟机指令的操作码。与前面的几种类型不同,returnAddress类型在Java语言之中并不存在相应的类型,也无法在程序运行期间更改returnAddress类型的值。

引用类型的变量保存引用的值,这个就是门牌,对应一个屋子,但是保存的是屋子的地址,也就是变量在内存中存储的首地址,一般包括:

类引用,接口引用,数组

堆和栈 这个比较的重要的概念,很有必要说一下。

程序运行的角度来说,一个程序能够运行起来,主要分为数据和逻辑,对应的就是堆和栈的对应关系。

栈,是程序运行时的逻辑存储的东西,比较标识方法的栈帧,表示程序运行时的单元。

堆,是程序运行时数据存储的地方,比如新建的对象,表示程序存储的单元。

栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;

堆解决的是数据存储的问题,即数据怎么放、放在哪儿。

在Java中一个线程就会相应有一个线程栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈。而堆则是所有线程共享的。栈因为是运行单位,因此里面存储的信息都是跟当前线程(或程序)相关信息的。包括局部变量、程序运行状态、方法返回值等等组合而成的栈帧;而堆只负责存储对象信息。

为什么这么设计?当初设计的JVM规范的那些大牛,为什么会把这两者区分开,我们只能根据自己的推测,来猜想一二了。

① 符合面向对象的理念,把变化的和和不变得分离(总感觉有太极中阴阳的感觉),我们可以知道面向对象和面向过程的程序在执行上或者说针对需求的满足上面没有什么区别,但是面向对象的引用更加的贴近自然的思考方式。我们在编写程序的时候,仔细的想想能够知道我们编写的类的成员的变量,对象的属性就是存放在堆中,但是方法就是存储在栈中,这样我们在编写对应对象的数据结构的时候,实际上就是处理了数据和对应的逻辑,实现了太极中统一。仔细想想面向对象的这种设计比较的美。

② 从软件设计的角度讲:栈代表的处理逻辑,而堆代表的是处理的数据,这样就把处理什么,和怎么处理分开了,是的处理的逻辑更加的清晰,这种模块化的,隔离的思想在软件设计的方方面面都有体现。

③ 堆和栈的分离,不仅使栈对应的线程能够更好的关注自己的处理逻辑,还能够使堆中的内容可以被对多个栈共享,可以理解多个线程访问同一个对象,这种情况提供了一种有效的数据交互的方式,比如共享数据。另一方面也节约了空间,当然线程安全也是一个问题。

④ 栈因为运行的需要,需要保存运行时的上下文,需要进行地址段的划分,栈中对数据的引用只是一个内存的首地址,所以这样的话,堆中的对象就能够根据需要动态的增长。

堆和栈分离了,那么堆中存储的是什么,栈中存储的又是什么?

堆中存的是对象,栈中存储的是基本数据类型和堆中对象的引用。一个对象的大小是不可估计的,或者说可以动态变化的,但是栈中对应的只存了一个引用,4个byte,所以说java程序理论上面有实例数的限制。

为什么把基本类型放在栈中,一个原因是因为占有的空间小,本身占用的空间就小,放在堆中有需要加上四个字节的引用,划不来,再说基本类型的的长度是固定的,不会出现动态的增长。

现在基本类型和对象的引用都是存放在栈中,而且都是几个字节的一个数,因此在逻辑处理的时候,能够保持一致,但是基本类型和对象引用,对象本身是有区别的,这个时候对应的一个基本的问题是,java中参数的传递问题:

Java中的参数传递时传值呢?还是传引用?
要说明这个问题,先要明确两点:
     1. 不要试图与C进行类比,Java中没有指针的概念。

2. 程序运行永远都是在栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传对象本身。

因此java的方法的调用,都是传值调用,但是传引用调用的错觉是怎么造成的:

在运行栈中,基本类型和引用的处理是一样的,都是传值,所以,如果是传引用的方法调用,也同时可以理解为“传引用值”的传值调用,即引用的处理跟基本类型是完全一样的。但是当进入被调用方法时,被传递的这个引用的值,被程序解释(或者查找)到堆中的对象,这个时候才对应到真正的对象。如果此时进行修改,修改的是引用对应的对象,而不是引用本身,即:修改的是堆中的数据。所以这个修改是可以保持的了。

对象,从某种意义上说,是由基本类型组成的。可以把一个对象看作为一棵树,对象的属性如果还是对象,则还是一颗树(即非叶子节点),基本类型则为树的叶子节点。程序参数传递时,被传递的值本身都是不能进行修改的,但是,如果这个值是一个非叶子节点(即一个对象引用),则可以修改这个节点下面的所有内容。

这一段是摘抄自网上的,感觉说的比较的好。

java中,栈的大小可以通过-Xss来设置,当栈中存储的数据比较多时,可以适当的调大这个值,否则会出现 java.lang.stackoverflowerror的异常,常见的出现的异常是循环递归的情况。堆的大小可以通过-Xmx3/ –Xms设置,后面我们详细的说。

说完了存储的结构,再说一下一个java对象到底有多大?

基本的数据类型是固定的,就不说了,在java中,一个空的Object对象的大小是8byte,并且这个大小事保存堆中一个没有任何属性对象的大小,如果包括引用,也就是Object instance = new Object(); 就是12byte,其中的4byte就是引用所占的空间。

Class Student{

int nmber;

boolean isGood;

Object teacher;

}

大小为:8(空的Object) + 4(int的大小)+1(boolean的大小)+4(teacher引用的大小) = 17byte,因为java中对对象内存分配的时候都是以8的整数倍来分的,依次分配为24,这个对象的大小就是24byte。

另外关于引用的,就是java中引用的分类:

强引用,软引用,弱引用,虚引用

各个类别,就不详细说了,因为在优化的过程中,我们的代码一般采取的就是强引用,软引用和弱引用一般的在处理缓存的逻辑中用到。

JVM基础和调优(一)的更多相关文章

  1. JVM基础和调优(六)

    JVM设置过程中的一般的规范 在JVM的设置中,年轻代的设置比较的重要,因为年轻代存储空间分配的比较的块,可以说触发GC的机会比较的大. 默认的情况下:-XX:NewRatio  默认为2 说明:年轻 ...

  2. JVM基础和调优(四)

    垃圾回收算法中的一些问题 再上一遍中,说道JVM并不是采用一种垃圾回收的方法,因为不同的内存块采取的方法是不样的,那么:为什么要分块?为什么不采用同一种方法回收垃圾,这样不是更加的统一吗? 分块的垃圾 ...

  3. JVM基础和调优(二)

    主要讲述java虚拟机的内存体系结构 了解了JVM 的一些基础之后,我们来看看java虚拟机内存的体系结构,这个是理解JVM垃圾收集算法的前提,理解了内存结构我们才能够针对不同的部分根据我们的程序进行 ...

  4. JVM基础和调优(五)

    垃圾回收算法中收集器 接着上面的说,了解了JVM收集垃圾的过程,然后我们看一看收集器. 串行收集器:用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高.但是,也无法使用多处理器的优势,所 ...

  5. JVM基础和调优(三)

    主要讲解垃圾回收的算法 上面我们已经了解到了,JVM的体系的结构,这次我们来说一下垃圾回收的算法. 1. 最开始的想法,或者说垃圾回收的最容易想到的就是:引用计数(reference count) 我 ...

  6. Java系列笔记(4) - JVM监控与调优

    目录 参数设置收集器搭配启动内存分配监控工具和方法调优方法调优实例     光说不练假把式,学习Java GC机制的目的是为了实用,也就是为了在JVM出现问题时分析原因并解决之.通过学习,我觉得JVM ...

  7. JVM监控与调优

    目录 参数设置收集器搭配启动内存分配监控工具和方法调优方法调优实例     转:http://www.cnblogs.com/zhguang/p/java-jvm-gc.html光说不练假把式,学习J ...

  8. [java] JVM监控与调优

    原文出处:http://www.cnblogs.com/zhguang/p/java-jvm-gc.html   光说不练假把式,学习Java GC机制的目的是为了实用,也就是为了在JVM出现问题时分 ...

  9. Tomcat性能调优-JVM监控与调优

    参数设置 在Java虚拟机的参数中,有3种表示方法用"ps -ef |grep "java"命令,可以得到当前Java进程的所有启动参数和配置参数: 标准参数(-),所有 ...

随机推荐

  1. 1346 - Songs (贪心)

    John Doe is a famous DJ and, therefore, has the problem of optimizing the placement of songs on his ...

  2. @SuppressWarnings(unchecked)作用解释

    解释一: 屏蔽某些编译时的警告信息 在强制类型转换的时候编译器会给出警告 加上 程序代码 @SuppressWarnings("unchecked") 就不会警告了 解释二: 注释 ...

  3. Node.js 博客实例(六)留言功能

    原教程https://github.com/nswbmw/N-blog/wiki/_pages的第六章,因为版本号等的原因,在原教程基础上稍加修改就可以实现. 实现用户给文章留言的功能,留言保存在数据 ...

  4. oracle 性能优化--索引总结

    索引是建立在表的一列或多个列上的辅助对象,目的是加快訪问表中的数据: Oracle存储索引的数据结构是B*树.位图索引也是如此,仅仅只是是叶子节点不同B*数索引: 索引由根节点.分支节点和叶子节点组成 ...

  5. zend_db连接mysql(附完整代码)(转)

    在看这些之前请确保你正确加载了PDO扩展. 作法是编辑php.ini手动增加下面这两行(前面要没有分号;):extension=php_pdo.dllextension=php_pdo_mysql.d ...

  6. 减少iOS应用程序安装包大小

    安装包优化大小方法: <资源优化> 1.去除无用资源 通过几次项目的升级后,项目中会出现一些没有用到的图片.这些图片在我们导入到项目中后,之后项目升级过程后并没有再次用到. 那这些图片我们 ...

  7. 服务 远程服务 AIDL 进程间通讯 IPC 深化

    示例 aidl接口文件 package com.bqt.aidlservice.aidl; parcelable Person;  package com.bqt.aidlservice.aidl; ...

  8. document.onclick vs window.onclick

    The JavaScript Window object is the highest level JavaScript object which corresponds to the web bro ...

  9. displaytag 简单使用流程

    1. 首先导入包:displaytag-1.2.jar,commons-lang.jar和standard.jar;commons-beanutils.jar;这四个jar包 2. 然后在jsp页面做 ...

  10. 生产环境 tomcat中启动缓慢

    具体的原因没研究,大概是一个随机数种子生成的速度拖慢了,直接copy一份解决方案,属于备忘材料 解决 有两种解决办法: 1)在Tomcat环境中解决 可以通过配置JRE使用非阻塞的Entropy So ...