本文环境

  1. win 10
  2. jdk 1.8.0_241
  3. IntelliJ 2019.1.3

一、通过Instrumentation获取内存

  1. 在java工程中添加如下代理类:
package com.nineya.memorymeasurs;
import java.lang.instrument.Instrumentation;public class MemoryMeasurs {static Instrumentation inst;// 由jvm注入public static void premain(String agentArgs, Instrumentation inst) {MemoryMeasurs.inst = inst;}// 取得对象大小public static long sizeOf(Object o) {if(inst == null) {throw new IllegalStateException("请在java的“-javaagent”命令行参数中运行。");}return inst.getObjectSize(o);}
}

上面的代理类能够实现基础的测量类对象内存占用的功能,在网上找到的更完整的版本如下,能够递归测量类对象引用的对象的占用的内存。

package com.nineya.memorymeasurs;import java.lang.instrument.Instrumentation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Stack;
/*** @author linsongwang* @date 2020/4/27*/public class MemoryMeasurs {static Instrumentation inst;// 由jvm注入public static void premain(String agentArgs, Instrumentation instP) {inst = instP;}// 计算对象内存占用public static long sizeOf(Object o) {if(inst == null) {throw new IllegalStateException("请在java的“-javaagent”命令行参数中运行。");}return inst.getObjectSize(o);}/*** 递归计算当前对象占用空间总大小,包括当前类和超类的实例字段大小以及实例字段引用对象大小*/public static long fullSizeOf(Object obj) {//深入检索对象,并计算大小Map<Object, Object> visited = new IdentityHashMap<Object, Object>();Stack<Object> stack = new Stack<Object>();long result = internalSizeOf(obj, stack, visited);while (!stack.isEmpty()) {//通过栈进行遍历result += internalSizeOf(stack.pop(), stack, visited);}visited.clear();return result;}//判定哪些是需要跳过的private static boolean skipObject(Object obj, Map<Object, Object> visited) {if (obj instanceof String) {if (obj == ((String) obj).intern()) {return true;}}return (obj == null) || visited.containsKey(obj);}private static long internalSizeOf(Object obj, Stack<Object> stack, Map<Object, Object> visited) {if (skipObject(obj, visited)) {//跳过常量池对象、跳过已经访问过的对象return 0;}visited.put(obj, null);//将当前对象放入栈中long result = 0;result += sizeOf(obj);Class <?>clazz = obj.getClass();if (clazz.isArray()) {//如果数组if(clazz.getName().length() != 2) {// skip primitive type arrayint length =  Array.getLength(obj);for (int i = 0; i < length; i++) {stack.add(Array.get(obj, i));}}return result;}return getNodeSize(clazz , result , obj , stack);}//这个方法获取非数组对象自身的大小,并且可以向父类进行向上搜索private static long getNodeSize(Class <?>clazz , long result , Object obj , Stack<Object> stack) {while (clazz != null) {Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (!Modifier.isStatic(field.getModifiers())) {//这里抛开静态属性if (field.getType().isPrimitive()) {//这里抛开基本关键字(因为基本关键字在调用java默认提供的方法就已经计算过了)continue;}else {field.setAccessible(true);try {Object objectToAdd = field.get(obj);if (objectToAdd != null) {stack.add(objectToAdd);//将对象放入栈中,一遍弹出后继续检索}} catch (IllegalAccessException ex) {assert false;}}}}clazz = clazz.getSuperclass();//找父类class,直到没有父类}return result;}
}
  1. 修改META-INF\MANIFEST.MF文件,添加如下行,引用上面的代理类
Premain-Class: com.nineya.memorymeasurs.MemoryMeasurs
  1. 在其他地方可以自由使用这个MemoryMeasurs代理类了。

  2. 编译工程为jar包,使用如下命令执行:

java -javaagent:XXX.jar main方法所在的类// 示例
java -javaagent:ObjectSize.jar  ObjectSizeTest

二、通过jol包

1.maven导包

        <dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.9</version></dependency>

2.使用api

import org.openjdk.jol.info.ClassLayout;// 取得map占用的空间
Map<String, String> map = new HashMap<>();
ClassLayout.parseInstance(map).instanceSize();

3.jol只是获取对象占用的内存空间,不会递归获取对象引用的其他对象占用的内存空间,稍微修改上面的MemoryMeasurs类进行封装。

package com.cl.graph.util;import org.openjdk.jol.info.ClassLayout;import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Stack;/*** @author linsongwang* @date 2020/4/27*/public class ObjectShallowSize {// 计算对象内存占用public static long sizeOf(Object o) {return ClassLayout.parseInstance(o).instanceSize();}/*** 深入检索对象,递归计算当前对象占用空间总大小,包括当前类和父类类的实例字段大小以及实例字段引用对象大小*/public static long fullSizeOf(Object obj) {//深入检索对象,并计算大小Map<Object, Object> visited = new IdentityHashMap<Object, Object>();Stack<Object> stack = new Stack<Object>();long result = internalSizeOf(obj, stack, visited);while (!stack.isEmpty()) {//通过栈进行遍历result += internalSizeOf(stack.pop(), stack, visited);}visited.clear();return result;}//判定哪些是需要跳过的private static boolean skipObject(Object obj, Map<Object, Object> visited) {if (obj instanceof String) {if (obj == ((String) obj).intern()) {return true;}}return (obj == null) || visited.containsKey(obj);}private static long internalSizeOf(Object obj, Stack<Object> stack, Map<Object, Object> visited) {if (skipObject(obj, visited)) {//跳过常量池对象、跳过已经访问过的对象return 0;}visited.put(obj, null);//将当前对象放入栈中long result = 0;result += sizeOf(obj);Class<?> clazz = obj.getClass();if (clazz.isArray()) {//如果数组if (clazz.getName().length() != 2) {// skip primitive type arrayint length = Array.getLength(obj);for (int i = 0; i < length; i++) {stack.add(Array.get(obj, i));}}return result;}return getNodeSize(clazz, result, obj, stack);}//这个方法获取非数组对象自身的大小,并且可以向父类进行向上搜索private static long getNodeSize(Class<?> clazz, long result, Object obj, Stack<Object> stack) {while (clazz != null) {Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (!Modifier.isStatic(field.getModifiers())) {//这里抛开静态属性if (field.getType().isPrimitive()) {//这里抛开基本关键字(因为基本关键字在调用java默认提供的方法就已经计算过了)continue;} else {field.setAccessible(true);try {Object objectToAdd = field.get(obj);if (objectToAdd != null) {stack.add(objectToAdd);//将对象放入栈中,一遍弹出后继续检索}} catch (IllegalAccessException ex) {assert false;}}}}clazz = clazz.getSuperclass();//找父类class,直到没有父类}return result;}public static long getGraphMemory(String graphName){Graph graph = GraphManage.getGraph(graphName);if (graph==null){System.out.println("图 "+graphName+" 不存在!");return 0;}System.out.println("递归获取内存中,该过程将非常长!");return fullSizeOf(graph);}
}

4.使用ObjectShallowSize获取对象内存占用

Map<String, String> map = new HashMap<>();
// 取得map占用的空间
ObjectShallowSize.sizeOf(map);
// 递归取得map占用的空间
ObjectShallowSize.fullSizeOf(map);

三、通过计算jvm内存空间取得

// gc操作
System.gc();
// startMemory=totalMemory(总内存)-freeMemory(剩余内存)
long startMemory = Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();// 在这里new需要测试内存占用的对象
...// gc操作
System.gc();
// endMemory=totalMemory(总内存)-freeMemory(剩余内存)
long endMemory = Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();Log.info("内存占用:"+ (endMemory-startMemory));

java取得对象占用的内存大小相关推荐

  1. 1 OC 对象的本质(一个NSObject 对象占用的内存大小)

    1 前言 目录 1 前言 2 一个NSObject占用多少内存 3 为什么呢 ? 4 如何在内存中看呢? OC 的面向对象都是基于C/C++ 的数据结构实现的 结构体 2 clang 命令转换成c++ ...

  2. Java 中对象占用内存大小计算

    原文地址 mp.weixin.qq.com byte 与 bit bit:位,比特.信息的最小单位,二进制数中的一个位数 (二进制位),其值为"0" 或"1": ...

  3. 如何查看java对象所占内存大小

    有时候我们需要对比看那种数据结构的Java对象占用的内存比较少,这时候我们就需要查看内存大小. 借助org.apache.lucene工具类 当一个对象有多个属性,需要计算整个对象的大小时,可以借助o ...

  4. java程序占用实际内存大小

    一.java程序占用实际内存大小 1.1.java命令启动参数-Xms -Xmx的问题         启动命令如下:java -server -Xms128m -Xmx128m -jar ****. ...

  5. android获取当前应用占用的内存大小,Android分析已安装应用占用内存

    问题 Android开发时可以通过AndroidStudio提供的一些系列工具查看应用的内存占用,十分的方便. 但是如果是对一个成品的已安装App快速查看内存占用呢,下面简单讲两种方式. 方案一:to ...

  6. Android中一张图片占用的内存大小

    最近面试过程中发现对Android中一些知识有些模棱两可,之前总是看别人的总结,自己没去实践过,这两天对个别问题进行专门研究 探讨:如何计算Android中一张图片占据内存的大小 解释:此处说的占据内 ...

  7. java应用程序占用高内存_对Java应用程序中的内存问题进行故障排除

    java应用程序占用高内存 重要要点 解决内存问题可能很棘手,但是正确的方法和正确的工具集可以大大简化此过程. Java HotSpot JVM可以报告几种OutOfMemoryError消息,因此务 ...

  8. C# CLR 聊聊对象的内存布局 一个空对象占用多少内存

    在 C# 中的对象大概可以分为三个不同的类型,包括值类型.引用类型和其他类型.本文主要讨论的是引用类型对内存空间的占用情况.在讨论开始之前我想问问大家,一个空的对象会占用多少内存空间?当然这个问题本身 ...

  9. 通过显示当前 python 程序占用的内存大小来比较生成器和迭代器(转载)

    # 显示当前 python 程序占用的内存大小 import osimport psutil as psutildef show_memory_info(hint):# 获取当前进程的进程号pid = ...

最新文章

  1. 摄像头与毫米波雷达(Radar)融合
  2. 解决MariaDB无法远程连接
  3. IP Cam须改原厂密码防黑客
  4. 非规范SQL的sharding-jdbc实践
  5. 当安全遇到大数据 “永恒之蓝”也将无所遁形!
  6. Android----获取activity上所有的控件
  7. Java DataOutputStream writeChars()方法及示例
  8. bootstrap中分页、面包屑导航、列表组、卡片、下拉菜单、折叠
  9. QT 线程池 + TCP 小试(三)实现最终功能
  10. Java快速入门学习笔记6 | Java语言中的for循环语句
  11. Phinx - 数据库迁移及版本控制介绍(内含中文文档翻译)
  12. springboot maven打包pom配置
  13. C++实现播放音频文件
  14. 微信菜单实现QQ在线聊天(一)
  15. Java | 内部类的实例化
  16. MTA18ASF2G72PDZ-2G6D1内存条MTA18ASF2G72PDZ-2G6E1
  17. 滴滴数据分析实习SQL笔试题
  18. 数据库毕业设计参考文献最新合集
  19. 贾玲,这次你是不是可以真的快乐了?
  20. 2010新财富中国富豪榜1至100名

热门文章

  1. MemFire教程|PostgreSQL RLS介绍
  2. 数据、信号、码元传输速率和信息传输速率等概念
  3. Python读取和操作Excel(.xlsx)文件
  4. Shell脚本笔记(3)- 变量子串
  5. OSGi架构学习与设计
  6. 最强悍的围棋人机对战程序 MoGo !
  7. java必备基础知识点
  8. ajax的同步与异步
  9. fastboot命令汇总
  10. RobotStudio仿真—Smart组件创建动态夹具