org.apache.maven.plugins maven-compiler-plugin 3.1 1.8 1.8 /src/test/** utf-8 org.apache.maven.plugins maven-jar-plugin 3.0.2 ${project.build.outputDirectory}/META-INF/MANIFEST.MF

在项目的 resources 中新建一个名为 META-INF 的目录,在这个目录下新建一个名为 MANIFEST.MF 的属性文件,如下图:

项目的JDK设置为1.8,如下图:

import java.lang.instrument.Instrumentation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set;
public class ObjectSizeFetcher {
    // instrumentation 是一个 java.lang.instrument.Instrumentation 的实例,由 JVM 自动传入
    private static Instrumentation instrumentation;
     *  这个方法先于主方法(main)执行
     * @param args
     * @param inst
    public static void premain(String args, Instrumentation inst) {
        instrumentation = inst;
     *  直接计算当前对象占用空间大小,包括当前类及超类的基本类型实例字段大小、
     *  引用类型实例字段引用大小、实例基本类型数组总占用空间、实例引用类型数组引用本身占用空间大小;
     *  但是不包括超类继承下来的和当前类声明的实例引用字段的对象本身的大小、实例引用数组引用的对象本身的大小
     * @param o 需要计算内存的对象
     * @return 返回内存大小
    public static long sizeOf(Object o) {
        return instrumentation.getObjectSize(o);
     * 递归计算当前对象占用空间总大小,包括当前类和超类的实例字段大小以及实例字段引用对象大小
     * 注意:这个方法如果你看不懂也没关系,会用就行 
     * @param objP
     * @return
     * @throws IllegalAccessException
    public static long fullSizeOf(Object objP) throws IllegalAccessException {
        Set<Object> visited = new HashSet<Object>();
        Deque<Object> toBeQueue = new ArrayDeque<>();
        toBeQueue.add(objP);
        long size = 0L;
        while (toBeQueue.size() > 0) {
            Object obj = toBeQueue.poll();
            //sizeOf的时候已经计基本类型和引用的长度,包括数组
            size += skipObject(visited, obj) ? 0L : sizeOf(obj);
            Class<?> tmpObjClass = obj.getClass();
            if (tmpObjClass.isArray()) {
                //[I , [F 基本类型名字长度是2
                if (tmpObjClass.getName().length() > 2) {
                    for (int i = 0, len = Array.getLength(obj); i < len; i++) {
                        Object tmp = Array.get(obj, i);
                        if (tmp != null) {
                            //非基本类型需要深度遍历其对象
                            toBeQueue.add(Array.get(obj, i));
            } else {
                while (tmpObjClass != null) {
                    Field[] fields = tmpObjClass.getDeclaredFields();
                    for (Field field : fields) {
                        if (Modifier.isStatic(field.getModifiers())   //静态不计
                                || field.getType().isPrimitive()) {    //基本类型不重复计
                            continue;
                        field.setAccessible(true);
                        Object fieldValue = field.get(obj);
                        if (fieldValue == null) {
                            continue;
                        toBeQueue.add(fieldValue);
                    tmpObjClass = tmpObjClass.getSuperclass();
        return size;
     * String.intern的对象不计;计算过的不计,也避免死循环
     * @param visited
     * @param obj
     * @return
    static boolean skipObject(Set<Object> visited, Object obj) {
        if (obj instanceof String && obj == ((String) obj).intern()) {
            return true;
        return visited.contains(obj);

计算一个对象的大小

我们在项目工程中新建一个名为Point的类,然后写一个main方法来测试new Point()占用内存空间的大小,代码如下:

public class Point {
    private int x;
    private int y;
    public static void main(String [] args) {
        System.out.println(ObjectSizeFetcher.sizeOf(new Point()));