Java中的序列化文件和C语言(JNI)中的'sizeof'运算符不相等
我有一个Java代码,它在Java本机接口的帮助下检查对象的大小(以字节为单位)。我将要确定其大小的对象作为参数传递。Java中的序列化文件和C语言(JNI)中的'sizeof'运算符不相等,java,c,macos,java-native-interface,osx-mavericks,Java,C,Macos,Java Native Interface,Osx Mavericks,我有一个Java代码,它在Java本机接口的帮助下检查对象的大小(以字节为单位)。我将要确定其大小的对象作为参数传递。 这是我的Java代码 Dog.java import java.io.Serializable; public class Dog implements Serializable { public static final int LEGS = 4; private double weight; private String breed;
这是我的Java代码 Dog.java
import java.io.Serializable;
public class Dog implements Serializable {
public static final int LEGS = 4;
private double weight;
private String breed;
public void setWeight(double weight) {
this.weight = weight;
}
public void setBreed(String breed) {
this.breed = breed;
}
public double getWeight() {
return weight;
}
public String getBreed() {
return breed;
}
}
DogTester.java
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class DogTester {
public native double getDogSize(Object dog);
static {
System.loadLibrary("DogTester");
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.setWeight(80.98);
dog.setBreed("Doberman");
DogTester tester = new DogTester();
System.out.println("Dog object required "+tester.getDogSize(dog)+" bytes");
try (FileOutputStream file = new FileOutputStream("Dog.ser");
ObjectOutputStream object = new ObjectOutputStream(file)) {
object.writeObject(dog);
} catch(IOException ioexception) {
System.out.println("IOException occured");
ioexception.printStackTrace();
}
}
}
我自己编写了这个头文件,而不是使用javah
狗测试仪
#include <jni.h>
#ifndef _Included_DogTester
#define _Included_DogTester
#ifdef __cplusplus
extern "C"
{
#endif
JNIEXPORT jdouble JNICALL Java_DogTester_getDogSize(jobject);
#ifdef __cplusplus
}
#endif
#endif
它生成了一个名为libDogTester.dylib
的文件
我将Java
程序编译为:
javac DogTester.java
它同时产生了DogTester.class
和Dog.class
并以以下方式运行代码:
java -Djava.library.path=. DogTester
结果如下:
Adityas-MacBook-Pro:Java aditya$ java -Djava.library.path=. DogTester
Dog object required 8.0 bytes
Size of object from C program = 8 bytes
这显然意味着我的dog
对象的大小是8字节。但是,右键单击由于序列化
Dog
对象而生成的Dog.ser
文件,并通过右键单击检查属性时,表示该文件占用81字节
而我的Java
和C
程序都说它只占用8个字节
现在我有三个问题
1>
即使.ser
文件只包含序列化对象,对象在序列化时是否会占用更多空间
2>
如果第一个问题的答案是否定的,那么为什么右键单击.ser
文件时,我会看到输出和获取信息部分给出的大小不同
3>
为什么即使在class DogTester
中的println()
方法之前调用了getDogSize()
方法,结果还是由Java
程序在C
程序printf()之前打印出来的
注:
当我在printf中添加\n
时(“C程序中对象的大小=%zu字节”,obj的大小)
过程在我的C
程序中,如下所示:
printf("Size of object from C program = %zu bytes\n", sizeof obj);
打印结果的顺序相反,新输出为:
Adityas-MacBook-Pro:Java aditya$ java -Djava.library.path=. DogTester
Size of object from C program = 8 bytes
Dog object required 8.0 bytes
有什么帮助吗?
提前感谢…对前两个问题的解答
1>
在序列化文件中,您保存的是dog
对象本身。
但是在程序中,您试图打印的是参考变量-dog
的大小,而不是dog
对象的大小。
因此,两者之间存在差异
2>
可能没有。实际上没有区别。仔细阅读第一个答案。它说明了我们看到不同结果的原因 sizeof操作符告诉您指向dog对象的指针的大小。而不是对象本身的大小。物体本身肯定比这个大。我猜是这样的
- 8字节对象开销
- 每个整数4个字节
- 每个方法8字节
- 8字节为双字节
- 字符串的x字节
你自己把它加起来,得到大小的近似值。jobject
是typedef
(同义词)表示void*
;它是指向对象的指针,而不是对象本身sizeof obj
提供指针的大小,而不是指向的对象的大小
编辑
为什么即使在DogTester类的println()方法之前调用了getDogSize()方法,结果还是在C程序printf()过程之前由Java程序打印
C语言中的标准输出通常是行缓冲的;在缓冲区已满或看到换行符之前,输出不会写入控制台。这就是为什么您在将\n
添加到C输出时看到行为的变化
我不会假装理解Java缓冲区相对于C是如何输出的,特别是当涉及JNI时,但从行为上可以清楚地看出,Java输出是在C输出之前刷新的
Edit2
:
7.21.3文件
…
3…当一个流被行缓冲时,字符被指定为
当输入新行字符时,作为块传输到主机环境或从主机环境传输
遇到。此外,字符打算作为块传输到主机
当缓冲区已填充、在未缓冲流上请求输入时的环境,或
当在需要传输数据的线路缓冲流上请求输入时
主机环境中的字符…
7在程序启动时,预先定义了三个文本流,无需显式打开
-标准输入(用于读取常规输入),标准输出(用于写入
常规输出)和标准错误(用于写入诊断输出)。一如当初
打开时,标准错误流未完全缓冲;标准输入与标准
当且仅当可以确定流不引用时,输出流才被完全缓冲
连接到交互式设备。
增加了重点。我认为你需要更多地浓缩和隔离你的问题。大多数人不会费力阅读5个来源的文件和你读过的小说wrote@BrandonYates我做不到。所有文件都相互依赖。请帮忙。我有三个小问题。你真的需要在你的帖子中用25行来向我展示“吠叫”和“咆哮”功能吗?@BrandonYates好的,我将删除它们对象序列化与sizeof
完全不同,它们都没有告诉你对象使用了多少内存。对象序列化记录类名、字段名以及标头等内容sizeof
告诉您jobject
句柄的大小,无论实际对象是什么,句柄大小都是相同的。我合法地回答了我自己的前两点问题。我需要第三个问题的答案。它能经受住法庭的审查吗?我们怎么能这么肯定这是合法的?是的,我们可以回答我们自己的问题。我接受回答
printf("Size of object from C program = %zu bytes\n", sizeof obj);
Adityas-MacBook-Pro:Java aditya$ java -Djava.library.path=. DogTester
Size of object from C program = 8 bytes
Dog object required 8.0 bytes