Alex‘s Blog

Coding My Life


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

记一次tomcat崩溃问题排查过程

发表于 2017-11-10 | 分类于 技术 , 学习 , JVM

产品在生产环境中跑了一段时间后,每天早晨运维人员都会发现程序崩溃,无法提供服务,重启之后就好了,而且白天都没问题,运维人员因此叫苦连天。

查看日志发现有堆内存溢出的提示,并且都是发生在凌晨一点钟左右,但找不到是哪个线程导致的,重启之后通过jstack、jmap、jstat等命令查看各项指标都正常。无奈只能在catalina.sh配置文件中加入JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/.../oom.hprof"配置项,当程序因为内存溢出崩溃时能够查看当时的jvm内存使用情况。

阅读全文 »

Java应用问题排查笔记

发表于 2017-11-07 | 分类于 技术 , 学习 , JVM

前一段时间跑在tomcat的java应用出现线程挂掉,CPU占用率持续过高,堆溢出的问题。首先说一下这件事的经过。

我在我的模块中有两个定时任务,使用的是spring boot的注解@Scheduled(fixedDelay=ONE_Minute),后来出现这了两个定时任务都不再往redis缓存里面存放数据的问题。一开始没有经验,也没有打印足够的日志,所以从日志里面也看不出啥问题。

后来,我去除掉了定时任务,改成了直接new线程的方式(这种方式当然不好),并且详细打上了日志。但又出现问题了,但可喜的是这两个线程中只有一个不工作了(就是不缓存数据了,具体问题也不清楚),另外一个还很正常。这种情况出现了2到3次,我这时候还是束手无策,不知为何?

阅读全文 »

第13章 线程安全与锁优化

发表于 2017-11-04 | 分类于 技术 , 学习 , JVM

线程安全

Java语言中的线程安全

我们可以将java语言中各种操作共享的数据分为以下5类:

  1. 不可变:1 final关键字修饰的变量(没有发生this引用逃逸的情况);2 Java.lang.String类的对象,调用它的方法是只会返回一个新构造的字符串对象;3 枚举类型;4 Long和Double等数值包装类型;
  2. 绝对线程安全:Java API中标注自己是线程安全的类,大多数都不是绝对的线程安全;
  3. 相对线程安全:相对的线程安全就是我们通常意义上所讲的线程安全,它需要保证对这个对象单独的操作是线程安全的。Vector、HashTable、Collections的synchronizedCollection()方法包装的集合等都属于这种类型;
  4. 线程兼容;
  5. 线程对立;
阅读全文 »

第12章 Java内存模型与线程

发表于 2017-11-04 | 分类于 技术 , 学习 , JVM

“内存模型”可以理解为在特定的操作协议下对特定的内存或高速缓存进行读写访问的过程抽象。

Java内存模型

1 主内存与工作内存

Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与Java编程中所说的变量有所区别,它包括了实例字段、静态字段和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的,不会被共享,自然就不会存在竞争问题。

工作过程:所有的变量都存储在主内存中。每条线程还有自己的工作内存(属于线程私有,类似处理器的高速缓存),线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量,线程间变量值的传递均需要通过主内存来完成。

2 内存间交互操作

Java内存模型中定义了一下8种操作来完成主内存和工作内存间的交互操作,虚拟机实现时必须保证下面提及的每一种操作都是原子的、不可再分的。

  1. lock
  2. unlock
  3. read
  4. load
  5. use
  6. assign
  7. store
  8. write
3 对于volatile型变量的特殊规则

在各个线程的工作内存中,volatile变量也可以存在不一致的情况,但是由于每次使用前都要先刷新,执行引擎看不到不一致的情况。

Java里面的运算并非原子操作,导致volatile变量的运算在并发下一样是不安全的。

阅读全文 »

Hyper-V之WMI、J-Interop

发表于 2017-11-03 | 分类于 技术 , 学习 , Hyper-V

概述

经过调研发现要通过调用WMI接口来实现对Hyper-V的管理,由于之前没有相关的经验所以通过网上搜索来理解什么是WMI。

关于使用何种编程语言调用WMI,微软官网给出的是封装很友好的c#和powershell脚本接口,但目前公司的开发语言主要为Java,所以经过调研是能使用J-Interop。J-Interop是一个基于Java语言的WMI封装库,但是用方式还是太过于原始,使用上不是很友好,还得需要进一步封装,当然这一部分不在本文的编写范围内。

什么是WMI?

官网介绍是:

Windows Management Instrumentation (WMI) is the Microsoft implementation of Web-Based Enterprise Management (WBEM), which is an industry initiative to develop a standard technology for accessing management information in an enterprise environment. WMI uses the Common Information Model (CIM) industry standard to represent systems, applications, networks, devices, and other managed components. CIM is developed and maintained by the Distributed Management Task Force (DMTF). About WMI.aspx)

以下WMI相关的内容转载自:http://blog.csdn.net/ilovepxm/article/details/6690224

阅读全文 »

在Hyper-V系列文章之前

发表于 2017-11-03 | 分类于 技术 , 学习 , Hyper-V

目前正在做公司的项目就快要验收了,打算将项目中与Hyper-V相关的笔记做一个整理。项目中我们的云管平台需要接管用户的hyper-v虚拟机,能够实现对Hyper-V虚拟机的新建、删除、修改、启动、停止、web console、客户端 console等功能,由于首次接触Hyper-V相关的东西,我的Hyper-V系列文章主要记录我的一些学习过程,希望我记录的东西能够帮助到大家,因为能够完成这个项目阶段的开发也是离不开大家的帮助。

git使用教程

发表于 2017-11-03 | 分类于 技术 , 学习

打算要复习一下git的使用方法,搜了几篇不错的文章。我就不直接照搬全文了,连接如下:

比较全面的教程:

Git使用教程,最详细,最傻瓜,最浅显,真正手把手教

针对几种应用场景的教程:

git入门,先学会这几个姿势

常用命令详解:
Git常用命令备忘,希望对学习Git的朋友们有所帮助

git进阶:

25个 Git 进阶技巧

第8章 虚拟机字节码执行引擎

发表于 2017-10-30 | 分类于 技术 , 学习 , JVM

在不同的虚拟机实现里面,执行引擎在执行Java代码的时候可能会有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择,可能能两者兼备,甚至还可能会包含几个不同级别的编译器执行引擎。

运行时栈帧结构

栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素。

栈帧存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息。

在编译程序代码的时候,栈帧中需要多大的局部变量表,多深的操作数栈都已经完全确定了,并且写入到方法表的Code属性中,因此一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

局部变量表

局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。

reference类型表示对一个对象实例的引用,虚拟机实现至少都应当能通过这个引用做到两点:

  1. 从此引用中直接或间接地查找到对象在Java堆中的数据存放的起始地址索引。
  2. 此引用中直接或间接地查找到对象所属数据类型在方法区中的存储的类型信息,否则无法实现Java语言规范中定义的语法约束约束。

Java语言中明确的64位的数据类型只有long和double两种。对于64位的数据类型,虚拟机会以高位对齐的方式为其分配两个连续的Slot空间。

虚拟机通过索引定位的方式使用局部变量表,索引值的范围是从0开始至局部变量表最大的Slot数量。

阅读全文 »

第7章 虚拟机类加载机制

发表于 2017-10-30 | 分类于 技术 , 学习 , JVM

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

在Java语言里,类型的加载、连接和初始化都是在程序运行期间完成的。

类加载的时机

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载。其中验证、准备、解析3个部分统称为连接。

解析阶段不一定:它在某些情况下可以在初始化阶段之后再开始,这个是为了支持Java语言的运行时绑定(也称动态绑定或晚期绑定)。

对于初始化阶段,虚拟机规范则是严格规定了有且只有5中情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始):

  1. 遇到new、getstatic、putstatic或invokestatic这4条字节指令时,如果类没有进行过初始化,则需要先触发其初始化。
  2. 使用java。lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
  3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  4. 当虚拟机启动时,用户需要制定一个要执行的主类,虚拟机会先初始化这个主类。
  5. 5 当使用JDK1.7动态语言支持是,…….

这5中场景中的行为成为对一个类进行主动引用,除此之外,所有引用类的方式都不会触发初始化,成为被动引用。

阅读全文 »

第6章 类文件结构

发表于 2017-10-30 | 分类于 技术 , 学习 , JVM

无关性的基石

各种不同平台的虚拟机与所有平台都统一使用的程序存储格式—字节码(ByteCode)是构成平台无关性的基石。
无关性:

  1. 平台无关性
  2. 语言无关性
    实现语言无关性的基础仍然是虚拟机和字节码存储格式。Java虚拟机不和包括Java在内的任何语言绑定,它只与“Class”这种特定的二进制文件格式所关联。

Class类文件的结构

  1. 任何一个Class文件都对应着唯一一个类或是接口的定义信息,但反过来说,类或接口并不一定都得定义在文件里。
  2. Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑第排列在Class文件中,中间没有任何分隔符。当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储(大端模式)。
  3. Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种结构中只有两种数据类型:无符号数和表。
  4. 无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串。
  5. 表是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以“_info”结尾。整个Class文件本质上就是一张表。
阅读全文 »
1…345
Alex Wong

Alex Wong

不管年龄大小,每个人都是我的老师

46 日志
57 分类
55 标签
Links
  • shalk
  • luckylau
© 2020 Alex Wong
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4