黑马程序员《JVM完整教程》笔记 - p001- p015

  • 引言
    • 什么是JVM?
    • 学习JVM有什么用?
  • 内存结构
    • 程序计数器
    • 虚拟机栈
      • 栈内存溢出
      • 线程运行诊断

b站链接: 黑马程序员JVM完整教程
下一篇连接: 黑马程序员《JVM完整教程》笔记 - p015 - p026

引言

什么是JVM?

Java Visual Machine程序的运行环境,(Java二进制字节码的运行环境)
JVM优点:

  • 一次编写,到处运行(平台无关性)
  • 自动内存管理,垃圾回收功能
  • 数组下标越界检查(危害到其他代码)
  • 多态

比较

  • 开发Java EE程序(JDK + 应用服务器 + IDE 工具)
  • 开发Java SE程序(JDK + IDE工具(集成开发环境))
  • JDK(JVM + 基础类库 + 编译工具)
  • JRE(JVM + 基础类库)
  • JVM
    < - > 操作系统(Windows,MacOS,Linux,Saloris)

学习JVM有什么用?

  • 面试
  • 理解底层的实现原理
  • 中高级程序员必备

常见的JVM

学习路线

方法区(Method Area):存放类
(Heap):存放类的实例、对象
虚拟机栈(JVM Stacks):调用方法用到
程序计数器(PC Register):调用方法用到
本地方法栈(Native Method Stacks):调用方法用到
本地方法接口:调用操作系统提供的方法
解释器(Interpreter):每行代码
即时编译器(JIT Compiler):热点代码
垃圾回收(GC):对堆中不在引用的对象进行回收

内存结构

程序计数器


定义
Program Counter Register程序计数器(寄存器)
特点

  • 是线程私有的
  • 不会存在内存溢出

作用:记住下一条jvm指令的执行地址

分别对应: 地址信息 JVM指令 java源代码
二进制字节码 - > 解释器 - > 机器码 - > CPU

虚拟机栈

:先进后出(特点)
虚拟机栈线程运行时需要的内存空间
栈帧:每个方法运行所需要的内存
栈帧包括:参数,局部变量,返回地址
-每个栈有多个栈帧组成
-每个线程只能有一个活动栈帧,对应着当前执行的方法

问题辨析

  1. 垃圾回收是否涉及栈内存?

栈内存,主要指方法调用的栈帧,每次方法调用后自动回收。
堆内存,垃圾回收主要回收堆内存中的对象。

/***演示栈帧*/
public class Demo1_1{public static void main(String[] args) throws InterruptedException {method1();}private static void method1(){method2(1, 2);}private static int method2(int a, int b){int c = a + b;return c;}
}


最上面为活动栈帧

  1. 栈内存分配越大越好吗?

VM option中 -Xss1m 指定栈帧大小为1m
一般情况默认栈帧:

  • Linux/x64 | MacOS | Oracle Solaris 1024kb
  • window 根据虚拟内存
    栈帧的内存划分大,则线程数变少
    栈划分大,可以进行多次的方法递归调用
  1. 方法内的局部变量是否线程安全?

局部变量是线程私有的,不会受到其他线程干扰
加static -> 线程共享,需要考虑线程安全的问题

  • 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的。
  • 如果局部变量引用了对象,并逃离方法的作用方法,需要考虑线程安全。
/***局部变量的线程安全问题*/
public class Demo1_2{// 多个线程同时执行此方法,不会造成x值混乱static void m1() {int x = 0;for (int i = 0; i < 5000; i++) {x++;}System.out.println(x);
}
public class Demo1_3 {public static void main(String[] args) {}public static void m1() { // 不需要考虑线程安全StringBuilder sb = new StringBuilder();sb.append(1);sb.append(2);sb.append(3);System.out.println(sb.toString());}public static void m2(StringBuilder sb) { // 作为参数传入,需要考虑线程安全sb.append(1);sb.append(2);sb.append(3);System.out.println(sb.toString());}public static StringBuilder m3() { // 作为返回值传出,需要考虑线程安全StringBuilder sb = new StringBuilder();sb.append(1);sb.append(2);sb.append(3);return sb;}
}

栈内存溢出

  • 栈帧过多导致栈内存溢出(情况较多)
  • 栈帧过大导致栈内存溢出
/*** 演示栈内存溢出 java.lang.StackOverflowError* -Xss256k*/
public class Demo1_4 {private static int count;public static void main(String[] args){try {method1();} catch (Throwable e) {e.printStackTree();System.out.println(count);}}private static void method1() {count++;method1();}
}

VM options:-Xss 256k 修改栈帧大小

public class Demo1_5 {public static void main(String[] args) throws JsonProgressingException {Dept d = new Dept();d.setName("Market");Emp e1 = new Emp();e1.setName("Zhang");e1.setDept(d);Emp e2 = new Emp();e2.setName("Li");e2.setDept(d);d.setEmps(Arrays.asList(e1, e2));// {name: 'Market', emp:[{name: 'Zhang', }]}ObjectMapper mapper  = new ObjectMapper();System.out.println(mapper.writeValueAsString(d));}
}
class Emp {private String name;@JsonIgnore // 打破循环private Dept dept;public String getName() {return name;}public void setName(String name) {this.name = name;}public Dept getDept() {return dept;}public void setDept(Dept dept) {this.dept = dept;}
}
class Dept {private String name;private List<Emp> emps;public String getName() {return name;}public void setName(String name) {this.name = name;}
......
}

线程运行诊断

案例1:cpu占用过多
定位

  • 用top定位哪个进程对cpu的占用过高
  • ps H -eo pid, tid, %cpu | grep 进程id (用ps命令进一步定位是哪个线程引起的cpu占用过高)
  • jstack 进程id
    • 可以根据线程id找到有问题的线程,进一步定位到问题代码的源码行号
[root@localhost ~]# nothup java cn.itcast.jvm.t1.Demo1_16 &

使用top实时监测

[root@localhost ~]# top


判断有问题的线程

[root@localhost ~]# ps H -eo pid,tid,%cpu|grep 32655

ps:查看线程对cpu的占用情况
H:打印进程的进程数,展示所有线程信息
pid:进程id
tid:线程id
%cpu:cpu占用
|grep:筛选,定位到具体进程

[root@localhost ~]# jstack 32655

将32665换算成十六进制进行比较找到具体问题线程(nid后4位)

案例2:程序运行很长时间没有结果

[root@localhost ~]# nothup java cn.itcast.jvm.t1.Demo1_3 &



发现死锁后,查看到Demo1_3 .java: 29 与 Demo1_3 .java: 21

public class Demo1_3 {static A a = new A();static B b = new B();public static void main(String[] args) {new Thread(()->{synchronized (a){try{Thread.sleep(2000);} catch(InterruptedException e){e.printStackTrace();}synchronized (b){System.out.println("我获得了 a 和 b");}}}).start();Thread.sleep(1000);new Thread(()->{synchronized (b){synchronized (a){System.out.println("我获得了 a 和 b");}}}).start();}
}

下一篇连接:黑马程序员《JVM完整教程》笔记 - p015 - p026

黑马程序员《JVM完整教程》笔记 - p001- p015相关推荐

  1. k8s之Pod详解(五)【Kubernetes(K8S) 入门进阶实战完整教程,黑马程序员K8S全套教程(基础+高级)】

    参考于Kubernetes(K8S) 入门进阶实战完整教程,黑马程序员K8S全套教程(基础+高级) Pod Pod的结构 每个Pod中都可以包含一个或者多个容器 这些容器可以分为两类: 用户自定义用的 ...

  2. 黑马程序员jvm笔记总集

    黑马程序员jvm笔记(一)–程序计数器 虚拟机栈 堆 黑马程序员jvm笔记(二)–方法区 串池 直接内存 黑马程序员jvm笔记(三)–垃圾回收部分心得 黑马程序员jvm笔记(四)–字节码部分心得 黑马 ...

  3. 黑马程序员全套Java教程_Java基础教程_异常(含扩展)(二十三)

    黑马程序员全套Java教程_Java基础教程_异常(含扩展)(二十三) 1.1 异常概述与异常体系结构 1.2 JVM遇到异常时的默认处理方案 1.3 异常处理 1.4 异常处理之try--catch ...

  4. 黑马程序员_java自学学习笔记(八)----网络编程

    黑马程序员_java自学学习笔记(八)----网络编程 android培训. java培训.期待与您交流! 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无 ...

  5. 【黑马程序员新版Linux学习笔记】Linux系统实用操作命令——操作演示

    [黑马程序员新版Linux学习笔记]Linux 零基础快速入门: (一)Linux基本命令--操作演示 (二)Linux用户和权限 -- 操作演示 (三)Linux 小技巧快捷键 (四)Linux系统 ...

  6. 【黑马程序员JVM学习笔记】01.引言

    1. 什么是JVM? 定义: Java Virtual Machine,Java程序的运行环境(Java二进制字节码的运行环境) 好处: 一次编写,到处运行 自动内存管理,垃圾回收功能 数组下标越界检 ...

  7. 黑马程序员-我的入学笔记1-关于C#.net基础

    ---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net ...

  8. 黑马程序员机器学习Day2学习笔记

    一.转换器和预估器 二. KNN算法 网格搜索和交叉验证 KNN案例:Facebook预测签到位置 朴素贝叶斯 联合概率.条件概率与相互独立 决策树 信息熵 回顾传统机器学习算法流程: 1.获取数据 ...

  9. 黑马程序员--SpringMVC详细教程

    一.SpringMVC概述 SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于 SpringFrameWork 的后续产品,已经融合在 Spr ...

  10. 尚硅谷+黑马程序员MongoDB视频学习笔记(一)

    本学习笔记是来源于学习B站上的尚硅谷和黑马的MongoDB教学视频而做的知识总结. 一.数据库(Database) 数据库是按照数据结构来组织.存在和管理数据的仓库.说白了,数据库就是存在数据的仓库. ...

最新文章

  1. MapReduce编程初体验
  2. 当你累了,准备放弃时,看看这个吧!!!
  3. CVPR2021|基于分类深度分布网络的单目3D物体检测
  4. 开通域名绑定DDNS
  5. Linear regression with one variable算法实例讲解(绘制图像,cost_Function ,Gradient Desent, 拟合曲线, 轮廓图绘制)_矩阵操作...
  6. .NET Core SignalR Redis底板详解(一)
  7. php中控车牌识别push协议,车牌识别一体机的RS485小接口——实现透明传输!
  8. qt tcp通信_Qt之网络编程TCP通信
  9. python出现的次数最多的元素_【Python 秘籍】序列中出现次数最多的元素
  10. sqlmap md5怎么解密_UC浏览器代理流量解密
  11. [渝粤教育] 西南科技大学 交通管理与控制 在线考试复习资料2021版
  12. jsp中java代码、jsp代码、js代码执行的顺序
  13. 深度学习教程(12) | CNN应用:目标检测(吴恩达·完整版)
  14. linux下多线程编程、线程间同步通信及应用详解、及踩过的坑
  15. 隐函数求导公式(多元隐函数存在定理)
  16. 确保软件开发生命周期(SDLC)的安全
  17. 第五期送书来了,这次送的都是畅销书!
  18. 统一依赖管理Composing builds
  19. 函数中arguments是什么?
  20. 给睡猫的学习计划(转载) by 冰血封情

热门文章

  1. hdu3031 N Knight
  2. 最快解决硬盘死锁|逻辑锁的方法
  3. ERP实施过程中的摘记
  4. Unity项目中不显示手柄
  5. WPF 实现测量显示文本长度
  6. 公司局域网无线AP测试方法
  7. Neuroimage | LMDA-Net第一作者亲自讲述其设计思想
  8. 国内首个区块链应用操作员职业资格培训项目启动库链云将成为核心教材
  9. c/c++中点运算符“.“和箭头运算符“→“的区别
  10. 小程序font-family