java对象占用内存分析
2016-07-11 11:30
211 查看
前言
空对象占8个字节
有数据成员的话,你把数据成员按基本数据类型和对象引用分开统计。
基本数据类型按byte/boolean=1,char/short=2,int/float=4,long/double=8,累加,然后对齐到8的倍数。
对象引用按每个4字节,累加,然后对齐到8个字节的倍数。
对象占用字节数=基本的8字节+基本数据类型所占的+对象引用所占的
比如
class A{
int a;
char b;
}
占 8(基本)+8(int 4+char 2=6,对齐到8)= 16个字节
再比如:
class B{
Integer a;
long b;
byte c;
}
占 8(基本)+8(long8+byte1=9,对齐到8)+8(对象引用4,对齐到8)=32个字节
===============
如果你是从别的类继承的,父类的也要算上。
直接上代码
实现类
public abstract class SizeOf {
private final Runtime s_runtime = Runtime.getRuntime();
/**
*
* 子类负责覆盖该方法以提供被测试类的实例
*
* @return 被测试类的实例
*/
protected abstract Object newInstance();
/**
*
* 计算实例的大小(字节数)
*
* @return 实例所占内存的字节数
* @throws Exception
*/
public int size() throws Exception {
// 垃圾回收
runGC();
// 提供尽可能多(10万)的实例以使计算结果更精确
final int count = 100000;
Object[] objects = new Object[count];
// 实例化前堆已使用大小
long heap1 = usedMemory();
// 多实例化一个对象
for (int i = -1; i < count; ++i) {
Object object = null;
// 实例化对象
object = newInstance();
if (i >= 0) {
objects[i] = object;
} else {
// 释放第一个对象
object = null;
// 垃圾收集
runGC();
// 实例化之前堆已使用大小
heap1 = usedMemory();
}
}
runGC();
// 实例化之后堆已使用大小
long heap2 = usedMemory();
final int size = Math.round(((float) (heap2 - heap1)) / count);
// 释放内存
for (int i = 0; i < count; ++i) {
objects[i] = null;
}
objects = null;
return size;
}
private void runGC() throws Exception {
// 执行多次以使内存收集更有效
for (int r = 0; r < 4; ++r) {
_runGC();
}
}
private void _runGC() throws Exception {
long usedMem1 = usedMemory();
long usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {
s_runtime.runFinalization();
s_runtime.gc();
Thread.currentThread().yield();
usedMem2 = usedMem1;
usedMem1 = usedMemory();
}
}
/**
*
* 堆中已使用内存
*
* @return 堆中已使用内存
*/
private long usedMemory() {
return s_runtime.totalMemory() - s_runtime.freeMemory();
}
}
测试
public class SizeOfObject extends SizeOf {
@Override
protected Object newInstance() {
return new Object();
}
public static void main(String[] args) throws Exception {
SizeOf sizeOf = new SizeOfObject();
System.out.println("所占内存:" + sizeOf.size() + "字节");
}
}
输出为:所占内存:8字节
利用序列化(Serializable)计算对象的大小
下面代码可以计算session的大小:
将session中的所有对象输出到文件中,文件的大小就是对象的大小.
try {
FileOutputStream f = new FileOutputStream("c:/sessionFiles");
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject("session:");
HttpSession session = request.getSession(false);
Enumeration names = session.getAttributeNames();
while(names.hasMoreElements()){
s.writeObject(session.getAttribute((String) names.nextElement()));
}
s.flush();
s.close();
f.close();
} catch (Exception e) {
e.printStackTrace();
}
空对象占8个字节
有数据成员的话,你把数据成员按基本数据类型和对象引用分开统计。
基本数据类型按byte/boolean=1,char/short=2,int/float=4,long/double=8,累加,然后对齐到8的倍数。
对象引用按每个4字节,累加,然后对齐到8个字节的倍数。
对象占用字节数=基本的8字节+基本数据类型所占的+对象引用所占的
比如
class A{
int a;
char b;
}
占 8(基本)+8(int 4+char 2=6,对齐到8)= 16个字节
再比如:
class B{
Integer a;
long b;
byte c;
}
占 8(基本)+8(long8+byte1=9,对齐到8)+8(对象引用4,对齐到8)=32个字节
===============
如果你是从别的类继承的,父类的也要算上。
直接上代码
实现类
public abstract class SizeOf {
private final Runtime s_runtime = Runtime.getRuntime();
/**
*
* 子类负责覆盖该方法以提供被测试类的实例
*
* @return 被测试类的实例
*/
protected abstract Object newInstance();
/**
*
* 计算实例的大小(字节数)
*
* @return 实例所占内存的字节数
* @throws Exception
*/
public int size() throws Exception {
// 垃圾回收
runGC();
// 提供尽可能多(10万)的实例以使计算结果更精确
final int count = 100000;
Object[] objects = new Object[count];
// 实例化前堆已使用大小
long heap1 = usedMemory();
// 多实例化一个对象
for (int i = -1; i < count; ++i) {
Object object = null;
// 实例化对象
object = newInstance();
if (i >= 0) {
objects[i] = object;
} else {
// 释放第一个对象
object = null;
// 垃圾收集
runGC();
// 实例化之前堆已使用大小
heap1 = usedMemory();
}
}
runGC();
// 实例化之后堆已使用大小
long heap2 = usedMemory();
final int size = Math.round(((float) (heap2 - heap1)) / count);
// 释放内存
for (int i = 0; i < count; ++i) {
objects[i] = null;
}
objects = null;
return size;
}
private void runGC() throws Exception {
// 执行多次以使内存收集更有效
for (int r = 0; r < 4; ++r) {
_runGC();
}
}
private void _runGC() throws Exception {
long usedMem1 = usedMemory();
long usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {
s_runtime.runFinalization();
s_runtime.gc();
Thread.currentThread().yield();
usedMem2 = usedMem1;
usedMem1 = usedMemory();
}
}
/**
*
* 堆中已使用内存
*
* @return 堆中已使用内存
*/
private long usedMemory() {
return s_runtime.totalMemory() - s_runtime.freeMemory();
}
}
测试
public class SizeOfObject extends SizeOf {
@Override
protected Object newInstance() {
return new Object();
}
public static void main(String[] args) throws Exception {
SizeOf sizeOf = new SizeOfObject();
System.out.println("所占内存:" + sizeOf.size() + "字节");
}
}
输出为:所占内存:8字节
利用序列化(Serializable)计算对象的大小
下面代码可以计算session的大小:
将session中的所有对象输出到文件中,文件的大小就是对象的大小.
try {
FileOutputStream f = new FileOutputStream("c:/sessionFiles");
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject("session:");
HttpSession session = request.getSession(false);
Enumeration names = session.getAttributeNames();
while(names.hasMoreElements()){
s.writeObject(session.getAttribute((String) names.nextElement()));
}
s.flush();
s.close();
f.close();
} catch (Exception e) {
e.printStackTrace();
}
相关文章推荐
- java.lang.UnsatisfiedLinkError: Native method not found:问题解决
- 使用IntelliJ IDEA 14和Maven创建java web项目
- 浅谈Java设计模式(二十二)中介者模式(Mediator)
- Java enum的用法
- java-----容器类总结之ArrayList与LinkedList的区别
- 【MyEclipse中项目红叉问题】 使用方案
- SpringMVC 取消拦截总结
- Java实现敏感词过滤
- 浅谈Java设计模式(二十一)访问者模式(Visitor)
- Eclipse配置PyDev插件
- 浅谈Java设计模式(二十)状态模式(State)
- Dubbo简单实例
- Spring单元测试
- spring 获取bean的几种方式
- Java RMI 框架(远程方法调用)
- Java泛型知识学习
- 浅谈Java的输入输出流(转)
- 浅谈Java设计模式(十九)备忘录模式(Memento)
- Eclipse内存溢出
- 使用 Struts 2 开发 RESTful 服务