1.整型数和浮点型数的表示

  原码:第一位为符号位(0为正数,1为负数)。

  反码:符号位不动,源码取反。

  正数补码:和原码相同。

  负数补码:符号位不动,反码加1。

  例如5的二进制表示可以是00000101,-6的表示:原码10000110,反码11111001,补码11111010,-1的表示:10000001,反码11111110,补码11111111

  补码的好处:0的表示唯一,数的符号位可以同数值部分作为一个整体参与运算,可以直接做加法,减法运算可以用加法来实现,即用求和来代替求差。

  例如:0的表示:正数00000000,负数10000000。

     -6+5                -4+5

       11111010         11111100

+00000101       +00000101

= 11111111      = 00000001

  打印正数的二进制表示

int a=-6;
for(int i=0;i<32;i++){
int t=(a & 0x80000000>>>i)>>>(31-i);
System.out.print(t);
}

  IEEE754浮点数的表示格式:s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

符号位(1)  指数位(8) 尾数(23)

          e全0 尾数附加位全0,否则尾数附加位为1

          s*m*2(e-127)

  例如:1 10000001 0100000000000000000000

  -1*2(129-127)*(20+2-2) = -5

  将单精度浮点数转成IEEE754二进制表示的代码示例:

package work.jvm;
public class ftob {
public static final int BITS = 32;
public static void main(String[] args) {
int i;
ftob ftb = new ftob();
float f = -9f;
System.out.println("float is:" + f);
int[] b = ftb.printBinaryFloat(f);
System.out.print("Binary is:");
for(i = 0; i < BITS; i++){
System.out.print(b[i]);
}
}
public int[] printBinaryFloat(float f){
int j;
int r[] = new int[32];
int temp = Float.floatToIntBits(f);
for(j = BITS-1; j >= 0; --j){
r[BITS-1-j] = ((temp>>j)&0x01);
}
return r;
}
}

2.jvm运行机制

  JVM启动过程:

  

  JVM基本结构:

  

  (1)PC寄存器:每个线程拥有一个PC寄存器,在线程创建时创建,指向下一条指令的地址,执行本地方法时,PC的值为undefined。

  (2)方法区:保存装载的类信息,如i类型的常量池、字段和方法信息、方法字节码,通常和永久区(Perm)关联在一起。

  (3)java堆:和程序开发密切相关,应用系统对象都保存在Java堆中,所有线程共享Java堆,对分代GC来说,堆也是分代的,GC的主要工作区间。

  

  (4)java栈:线程私有,栈由一系列帧组成(因此Java栈也叫做帧栈),帧保存一个方法的局部变量、操作数栈、常量池指针,每一次方法调用创建一个帧,并压栈。

    栈上分配:小对象(一般几十个bytes),在没有逃逸的情况下,可以直接分配在栈上,直接分配在栈上,可以自动回收,减轻GC压力,大对象或者逃逸对象无法栈上分配。

  (5)堆、栈、方法区交互:

public class AppMain
//运行时, jvm 把appmain的信息都放入方法区
{
public static void main(String[] args)
//main 方法本身放入方法区。
{
Sample test1 = new Sample("测试1");
//test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面
Sample test2 = new Sample("测试2");
test1.printName(); test2.printName();
}
}
public class Sample
//运行时, jvm 把appmain的信息都放入方法区
{
private name;
//new Sample实例后,name引用放入栈区里,name对象放入堆里
public Sample(String name)
{
this.name = name;
}
//print方法本身放入 方法区里。
public void printName()
{
System.out.println(name);
}
}
 
3.jvm配置参数
  (1)Trace跟踪参数 
  -verbose:gc
  -XX:+printGC

可以打印GC的简要信息
  -XX:+PrintGCDetails 打印GC详细信息
  -XX:+PrintGCTimeStamps 打印CG发生的时间戳
  -Xloggc:log/gc.log 指定GC log的位置,以文件输出
  -XX:+TraceClassLoading 监控类的加载
  -XX:+PrintClassHistogram 按下Ctrl+Break后,打印信息 分别显示:序号、实例数量、总大小、类型
  (2)堆分配参数
  -Xmx –Xms 指定最大堆和最小堆,例如:-Xmx20m -Xms5m
  -Xmn 设置新生代大小
  -XX:NewRatio 新生代(eden+2*s)和老年代(不包含永久区)的比值,比如4 表示新生代:老年代=1:4,即年轻代占堆的1/5。
  -XX:SurvivorRatio 设置两个Survivor区和eden的比,比如8表示 两个Survivor :eden=2:8,即一个Survivor占年轻代的1/10。
  -XX:+HeapDumpOnOutOfMemoryError,OOM时导出堆到文件。
  -XX:+HeapDumpPath 导出OOM的路径。
  -XX:OnOutOfMemoryError 在OOM时,执行一个脚本。例如:
    -XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p,其中printstack.bat里脚本为D:/tools/jdk1.7_40/bin/jstack -F %1 > D:/a.txt。
    当程序OOM时,在D:/a.txt中将会生成线程的dump
    也可以在OOM时,发送邮件,甚至是重启程序
  (3)栈分配参数
  -Xss 通常只有几百K,决定了函数调用的深度,每个线程都有独立的栈空间,局部变量、参数 分配在栈上。
  (4)永久区
  -XX:PermSize  -XX:MaxPermSize
  (5)堆分配参数建议
    根据实际事情调整新生代和幸存代的大小
    官方推荐新生代占堆的3/8
    幸存代占新生代的1/10
    在OOM时,记得Dump出堆,确保可以排查现场问题
4.GC算法
  (1)引用计数算法
  引用计数器的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的应用计数器的值为0,则对象A就不可能再被使用,就可以清除了。像python和actionscript用的就是引用计数算法。引用计数有两个问题:i引用和去引用伴随加法和减法,影响性能;ii很难处理循环引用。这个算法java并没有采用。
  (2)标记清除
  标记-清除算法是现代垃圾回收算法的思想基础。标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。
  (3)标记压缩
  标记-压缩算法适合用于存活对象较多的场合,如老年代。它在标记-清除算法的基础上做了一些优化。和标记-清除算法一样,标记-压缩算法也首先需要从跟节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。
  (4)复制算法
  与标记-清除算法相比,复制算法是一种相对高效的回收方法。不适用于存活对象较多的场合,如老年代。将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。年轻代的from和to两个区(也叫s1和s2)就是复制算法的两个区。
  gc可能引发stop the world(STW)现象。STW是Java中一种全局暂停的现象,这个时候所有Java代码停止运行,native代码可以执行,但不能和JVM交互。原因多半由GC引起,还有dump线程,死锁检查,堆dump也有可能引发STW。危害:i长时间(零点几秒到几十秒,甚至更长)服务停止,没有响应;ii遇到HA系统,可能引起主备切换,严重危害生产环境。
5.分代思想与可触及性
  分代思想:依据对象的存活周期进行分类,短命对象归为新生代,长命对象归为老年代。

  根据不同代的特点,选取合适的收集算法:
    少量对象存活,适合复制算法。
    大量对象存活,适合标记清理或者标记压缩。
  可触及性:
    可触及的:-从根节点可以触及到这个对象。

    可复活的:-旦所有引用被释放,就是可复活状态,因为在finalize()中可能复活该对象。
    不可触及的:-在finalize()后,可能会进入不可触及状态,不可触及的对象不可能复活,可以被回收。
6.GC参数
  (1)串行收集器。最古老,最稳定,

效率高,
可能会产生较长的停顿。
 
    参数:
-XX:+UseSerialGC
      –新生代、老年代使用串行回收
      –新生代复制算法
      –老年代标记-压缩
  
  (2)并行收集器
  
  ParNew收集器
    -XX:+UseParNewGC
    新生代并行,老年代串行
    Serial收集器新生代的并行版本
    复制算法
    多线程,需要多核支持
    -XX:ParallelGCThreads 限制线程数量
  Parallel收集器
    类似ParNew,新生代复制算法,老年代 标记-压缩,更加关注吞吐量。
    -XX:+UseParallelGC  使用Parallel收集器+ 老年代串行。
    -XX:+UseParallelOldGC  使用Parallel收集器+ 并行老年代。
    -XX:MaxGCPauseMills  最大停顿时间,单位毫秒,GC尽力保证回收时间不超过设定值。
    -XX:GCTimeRatio  0-100的取值范围,垃圾收集时间占总时间的比,默认99,即最大允许1%时间做GC。
 
  (3)CMS收集器
    Concurrent Mark Sweep 并发标记清除,这个并发的意思是与用户现场一起执行。
    标记-清除算法
    与标记-压缩相比,并发阶段会降低吞吐量
    老年代收集器(新生代使用ParNew)
    -XX:+UseConcMarkSweepGC
    -XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次整理,整理过程是独占的,会引起停顿时间变长。

    -XX:+CMSFullGCsBeforeCompaction,设置进行几次Full GC后,进行一次碎片整理。
    -XX:ParallelCMSThreads,设定CMS的线程数量。
    CMS运行过程比较复杂,着重实现了标记的过程,可分为
      i.初始标记。根可以直接关联到的对象,速度快。
      ii.并发标记。(和用户线程一起)。主要标记过程,标记全部对象。
      iii.重新标记。由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正。
      iv.并发清除(和用户线程一起)。基于标记结果,直接清理对象
    特点:

      尽可能降低停顿,会影响系统整体吞吐量和性能。比如,在用户线程运行过程中,分一半CPU去做GC,系统性能在GC阶段,反应速度就下降一半。
      清理不彻底,因为在清理阶段,用户线程还在运行,会产生新的垃圾,无法清理。
      因为和用户线程一起运行,不能在空间快满时再清理。-XX:CMSInitiatingOccupancyFraction设置触发GC的阈值,如果不幸内存预留空间不够,就会引起concurrent mode failure。
  (4)几个实例
    以32M堆启动tomcat
  set CATALINA_OPTS=-server -Xloggc:gc.log -XX:+PrintGCDetails -Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:+UseSerialGC -XX:PermSize=32M 
  以512M堆启动tomcat
  set CATALINA_OPTS=-Xmx512m -Xms64m -XX:MaxPermSize=32M  -Xloggc:gc.log -XX:+PrintGCDetails -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=4
  (5)最后汇总一下GC参数:
    -XX:+UseSerialGC:在新生代和老年代使用串行收集器

    -XX:SurvivorRatio:设置eden区大小和survivior区大小的比例
    -XX:NewRatio:新生代和老年代的比
    -XX:+UseParNewGC:在新生代使用并行收集器
    -XX:+UseParallelGC :新生代使用并行回收收集器
    -XX:+UseParallelOldGC:老年代使用并行回收收集器
    -XX:ParallelGCThreads:设置用于垃圾回收的线程数
    -XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器
    -XX:ParallelCMSThreads:设定CMS的线程数量
    -XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发
    -XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理
    -XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收后,进行一次内存压缩
    -XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收
    -XX:CMSInitiatingPermOccupancyFraction:当永久区占用率达到这一百分比时,启动CMS回收
    -XX:UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收
 
这一篇文章先写到这里,下一篇继续^-^
 
  
  
 

jvm基础(1)的更多相关文章

  1. JVM 基础知识

    JVM 基础知识(GC) 2013-12-10 00:16 3190人阅读 评论(1) 收藏 举报 分类: Java(49) 目录(?)[+] 几年前写过一篇关于JVM调优的文章,前段时间拿出来看了看 ...

  2. java 笔记(1)-—— JVM基础,内存数据,内存释放,垃圾回收,即时编译技术JIT,高精度类型

    1.java中5个存放数据的地方: (1).寄存器(Registers):位于CPU内部,是速度最快的存储区,但是数量和容量有限.在java中不能直接操作寄存器. (2).栈(Stack):栈位于通用 ...

  3. JVM基础:深入学习JVM堆与JVM栈

    转自:http://developer.51cto.com/art/201009/227812.htm JVM栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;JVM堆解决的是数据存储的问题, ...

  4. JVM基础知识(1)-JVM内存区域与内存溢出

    JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...

  5. Jvm基础(2)-Java内存模型

    Jvm基础(2)-Java内存模型 主内存和工作内存 Java内存模型包括主内存和工作内存两个部分:主内存用来存储线程之间的共享变量:而工作内存中存储每个线程的相关变量. 如下图所示: 需要注意的是: ...

  6. 剑指Offer——知识点储备-JVM基础

    剑指Offer--知识点储备-JVM基础 1.java内存与内存溢出 1.1 JVM分为哪些区,每一个区干嘛的?(见java虚拟机38页) (1)程序计数器(线程私有) 当前线程执行字节码的信号指示器 ...

  7. JVM基础系列第15讲:JDK性能监控命令

    查看虚拟机进程:jps 命令 jps 命令可以列出所有的 Java 进程.如果 jps 不加任何参数,可以列出 Java 程序的进程 ID 以及 Main 函数短名称,如下所示. $ jps 6540 ...

  8. JVM基础系列第14讲:JVM参数之GC日志配置

    说到 Java 虚拟机,不得不提的就是 Java 虚拟机的 GC(Garbage Collection)日志.而对于 GC 日志,我们不仅要学会看懂,而且要学会如何设置对应的 GC 日志参数.今天就让 ...

  9. JVM基础系列第13讲:JVM参数之追踪类信息

    我们都知道 JVM 在启动的时候会去加载类信息,那么我们怎么得知他加载了哪些类,又卸载了哪些类呢?我们这一节就来介绍四个 JVM 参数,使用它们我们就可以清晰地知道 JVM 的类加载信息. 为了方便演 ...

  10. JVM基础系列第11讲:JVM参数之堆栈空间配置

    JVM 中最重要的一部分就是堆空间了,基本上大多数的线上 JVM 问题都是因为堆空间造成的 OutOfMemoryError.因此掌握 JVM 关于堆空间的参数配置对于排查线上问题非常重要. tips ...

随机推荐

  1. 使用grunt实现自动化单元测试

    闲话不多说~ 使用步骤 1.安装插件 npm install grunt-contrib-qunit --save-dev 2.加载包含 "qunit" 任务的插件 grunt.l ...

  2. 刷题总结——怪题(ssoj费用流)

    题目: 题目描述 给出一个长度为 n 的整数序列 hi ,现在要通过一些操作将这个序列修改为单调不降序列,即  hi≤hi+1 . 可以用的操作有 m 种,第 i 种操作可以通过支付 ci 的代价将一 ...

  3. mybatis学习(九)——动态sql

    MyBatis 的强大特性之一便是它的动态 SQL.可以根据不同条件拼接 SQL 语句. 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似.主要由以下几种元素. if wh ...

  4. javaweb学习总结(十四)——JSP原理(转)

    一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...

  5. Struts+ibatis-学习总结二

    1封装json 在Action中以传统方式输出JSON数据 这一点跟传统的Servlet的处理方式基本上一模一样,代码如下 public void doAction() throws IOExcept ...

  6. LeetCode OJ--Best Time to Buy and Sell Stock II

    http://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ 第二问,是说可以进行无数次买卖. 贪心法 #include &l ...

  7. AC日记——线段树练习5 codevs 4927

    4927 线段树练习5  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 有n个数和5种操作 add a b ...

  8. Hdoj 3506 Monkey Party

    Discription Far away from our world, there is a banana forest. And many lovely monkeys live there. O ...

  9. Maven 项目打包发布

    在Eclipse左侧右击项目,Debug As -> Debug Configurations -> 双击Maven Build 然后看弹出框的右侧右侧的Name随便填写一个名字,Base ...

  10. Wdatepick控件只能选当前时间以前的时间

    WdatePicker限制只能选当天,只能选以前的时间 (1)WdatePicker限制只能选以前的时间(不能选当天): onfocus="WdatePicker({startDate:'% ...