java - Convert a byte array to a class? - java

In C/C++, you can do the following:
struct DataStructure
{
char member1;
char member2;
};
DataStructure ds;
char bytes[] = {0xFF, 0xFE};
memcpy(&ds, bytes, sizeof(ds));
and you would essentially get the following:
ds.member1 = 0xFF;
ds.member2 = 0xFE;
What is the Java equivalent?

What is the Java equivalent?
There is no Java equivalent.
Java does not allow you to create or modify objects by accessing them at that level. You should be using new or setter methods, depending on what you are trying to achieve.
(There are a couple of ways to do this kind of thing, but they are unsafe, non-portable and "not Java" ... and they are not warranted in this situation.)

The memcpy you wrote depends on the internal implementation of the struct and would not necessarily work. In java, you need to define a constructor that accepts a byte array and set the fields. No shortcuts like this, as the memory structure of the class is not defined.

In Java you cannot work with the memory directly (no memcpy) it is the advantage (disadvantage?) of Java. There are some java library methods to copy arrays: System.arraycopy().
In general, to copy some object you need to ship it with clone method.

You might be able to do that in C. But you'd be wandering into aliasing problems and a hunka hunka burning undefined behavior.
And because struct padding is up to a compiler, what you might get with your memcpy is just ds.member1 = 0xFF, ds.member2 = whatever junk happened to be on the stack at the time, because member1 was padded to occupy 4 bytes rather than just 1. Or maybe you get junk for both, because you set the top 2 bytes of a 4-byte and they're in the bottom 2 bytes.
What you're wandering into is compiler/runtime-specific memory layouts. The same is true in Java. Java itself won't let you do something so horrendously un-Java, but if you write your own JVM or debug an existing JVM written in C or C++, you could do something like that. And who knows what would happen; I'm not Java god enough to know exactly how much the JVM spec pins down JVM implementation, but my guess is, not to the degree necessary to enable interoperability of the in-memory, runtime representations of objects.
So you get undefined behavior in every language flavor. Tastes just as good in each language, too - like mystery meat.

Related

How to create C style union in java?

I have to convert one of my code segment from C to java. Code is given below.
union commandString{
char commndStr[20];
struct{
char commnd[4];
char separator1;
char agr1[5];
char separator2;
char arg2[3];
char separator3;
char additionalArg[5];
};
};
I don't want to use any explicit parser or I do not want to use
System.arraycopy
method.
Is there any way to do that in my preferred way?
The Java language does not support unions or direct control memory layout the way that languages like C do directly.
However Oracle does offer a backdoor that was added in Java 5 that can be used by using the class sun.misc.Unsafe. It takes a bit of work, the full details have been documented by Martin Thompson on his blog.
The other option would be to write it in C and access it from Java as native functions via JNI.
The best library for doing Struct and Union would be Javolutions which has been around for many years. These were designed to do this.
I suggest if you are going to use these Unsafe you wrap it up in a library which abstracts it away. This can avoid continuously running into bugs which crash your JVM (and I mean crash in the sense a C programmer would understand)
I have a library called Java-Lang which allows you to do the sort of things Java doesn't normally allow such as 63 bit sized off heap and memory mapped, thread safe off heap operations, sharing of memory between JVM on the same machine. And as I said, I use my own library to abstract away use of Unsafe.
Reading about the Javolution Union led me to ByteBuffer, which can be used as a Union. Being an Abstract Class with only one provided class, you may need to create a temp file using File.createTempFile(), a RandomAccessFile(File,"rw"), a FileChannel RandomAccessFile.getChannel(), a MappedByteBuffer FileChannel.map(). It has controls for whether you want a big endian (default) or little endian relationship of bytes to other types. If you just need one Union for mapping types to bytes, such as for a trie, this would suffice.

Byte based (de)serialization in Java?

I want to try abusing Java classes as structures and for that I'm wondering if it is possible to serialize a byte array to a class and other way around.
So if I have a class like this:
public class Handshake
{
byte command;
byte error;
short size;
int major;
int ts;
char[] secret; // aligned size = 32 bytes
}
Is there an easy way (without having to manually read bytes and fill out the class which requires 3 times as much code) to deserialize a set of bytes into this class? I know that Java doesn't have structs but I'm wondering if it is possible to simplify the serialization process so it does it automatically. The bytes are not from Java's serializer, they are just aligned bytes derived from C structs.
The bytes are not from Java's serializer, they are just aligned bytes
derived from C structs.
Bad idea. It can break as soon as someone compiles that code on a different platform, using a different compiler or settings, etc.
Much better: use a standardized binary interface with implementations in Java and C++ like ASN.1 or Google's Protocol Buffers.
You can write a library to do the deserializtion using reflection. This may result in more code being required, but may suit your needs. It worth nothing that char in Java 16-bit rather than 8 bit and a char[] is a separate Object, unlike in C.
In short you can write a library which reads this data without touching the Handshake class. Only you can decide if this is actually easier than adding a method or two to the handshake class..
Do not do that! I will break sooner or later. Use some binary serialization format, like [Hessian][1], which supports both java and C++ (I'm not aware of anything that works on plain C)
Also remember C does not force size for int's or long's, they are platform dependent.
So if you must use C, and you are forced to write your own library, be very careful.

what is the size of empty class in C++,java?

What is the size of an empty class in C++ and Java?
Why is it not zero?
sizeof(); returns 1 in the case of C++.
Short Answer for C++:
The C++ standard explicitly says that a class can not have zero size.
Long Answer for C++:
Because each object needs to have a unique address (also defined in the standard) you can't really have zero sized objects.
Imagine an array of zero sized objects. Because they have zero size they would all line up on the same address location. So it is easier to say that objects can not have zero size.
Note:
Even though an object has a non zero size, if it actually takes up zero room it does not need to increase the size of derived class:
Example:
#include <iostream>
class A {};
class B {};
class C: public A, B {};
int main()
{
std::cout << sizeof(A) << "\n";
std::cout << sizeof(B) << "\n";
std::cout << sizeof(C) << "\n"; // Result is not 3 as intuitively expected.
}
g++ ty.cpp
./a.out
1
1
1
In the Java case:
There is no simple way to find out how much memory an object occupies in Java; i.e. there is no sizeof operator.
There are a few ways (e.g. using Instrumentation or 3rd party libraries) that will give you a number, but the meaning is nuanced1; see In Java, what is the best way to determine the size of an object?
The size of an object (empty or non-empty) is platform specific.
The size of an instance of an "empty class" (i.e. java.lang.Object) is not zero because the instance has implicit state associated with it. For instance, state is needed:
so that the object can function as a primitive lock,
to represent its identity hashcode,
to indicate if the object has been finalized,
to refer to the object's runtime class,
to hold the object's GC mark bits,
and so on.
Current Hotspot JVMs use clever tricks to represent the state in an object header that occupies two 32 bit words. (This expands in some circumstances; e.g. when a primitive lock is actually used, or after identityHashCode() is called.)
1 - For example, does the size of the string object created by new String("hello") include the size of that backing array that holds the characters? From the JVM perspective, that array is a separate object!
Because every C++ object needs to have a separate address, it isn't possible to have a class with zero size (other than some special cases related to base classes). There is more information in C++: What is the size of an object of an empty class? .
Because an object has to have an address in memory, and to have an address in memory, it has to occupy "some" memory. So, it is usually, in C++, the smallest possible amount, i.e. 1 char (but that might depend on the compiler). In Java, I wouldn't be so sure.. it might have some default data (more than just a placeholder like in C++), but it would be surprising if it was much more than in C++.
C++ requires that a normal instantiation of it have a size of at least 1 (could be larger, though I don't know of a compiler that does that). It allows, however, an "empty base class optimization", so even though the class has a minimum size of 1, when it's used as a base class it does not have to add anything to the size of the derived class.
I'd guess Java probably does pretty much the same. The reason C++ requires a size of at least 1 is that it requires each object to be unique. Consider, for example, an array of objects with size zero. All the objects would be at the same address, so you'd really only have one object. Allowing it to be zero sounds like a recipe for problems...
It's defined by the C++ standard as "a nonzero value", because an allocated object must have a nonzero size in order to have a distinct address. A class that inherits from an empty class, however, is not required to increase in size, barring the usual increase of a vtable if there are virtual functions involved.
I don't know if there is a sizeof() operator in java. What you can do is create an instance of the empty class (have it serializable), send it through a PipedOutputStream and read it as byte array - byteArray.length gives you the size.
Alternatively, write out the instance to a file using DataOutputStream, close the File, open it and file.length() will give you the size of the Object. Hope this helps, - M.S.
As others have pointed out, C++ objects cannot have zero size. Classes can have zero size only when they act as a subclass of a different class. Take a look at #Martin York's answer for a description with examples --and also look and vote the other answers that are correct to this respect.
In Java, in the hotspot VM, there is a memory overhead of 2 machine-words (usually 4 bytes in a 32 arch per word) per object to hold book keeping information together with runtime type information. For arrays a third word is required to hold the size. Other implementations can take a different amount of memory (the classic Java VM, according to the same reference took 3 words per object)

JNI: equivalent of uint *vboIds in Java

I'm developing a java application that uses some jni calls.
I have on C code the following variable:
GLuint *vboIds;
I want to pass this variable from Java to C, but I don't know how to declare it in Java.
GLuint is equivalent an unsigned int.
So, I think this is the equivalent declaration in Java:
int[] vboIds;
What do you think?
Thanks
You don't say explicitly whether it is meant to be a pointer to a single value or an array, but I'd guess it's probably an array from the naming and what you are thinking of doing with the mapping (there should also be a parameter somewhere that specifies the length of the array; those both map to the same argument on the Java side as Java's arrays know their own lengths). You're probably right to use an int as that's generally the same size as a C int – not that that's a guarantee, not at all, but hardly any machine architectures are different from that these days – but you'll need to watch out for the fact that Java's numeric types are all signed. That's mostly not a problem provided you're a bit careful with arithmetic (other than addition, subtraction and left-shift, which work obviously) and comparisons.

What is the 'correct' way to store a native pointer inside a Java object?

What is the 'correct' way to store a native pointer inside a Java object?
I could treat the pointer as a Java int, if I happen to know that native pointers are <= 32 bits in size, or a Java long if I happen to know that native pointers are <= 64 bits in size. But is there a better or cleaner way to do this?
Edit: Returning a native pointer from a JNI function is exactly what I don't want to do. I would rather return a Java object that represents the native resource. However, the Java object that I return must presumably have a field containing a pointer, which brings me back to the original question.
Or, alternatively, is there some better way for a JNI function to return a reference to a native resource?
IIRC, both java.util.zip and java.nio just use long.
java.nio.DirectByteBuffer does what you want.
Internally it uses a private long address to store pointer value. Dah !
Use JNI function env->NewDirectByteBuffer((void*) data, sizeof(MyNativeStruct)) to create a DirectByteBuffer on C/C++ side and return it to Java side as a ByteBuffer. Note: It's your job to free this data at native side! It miss the automatic Cleaner available on standard DirectBuffer.
At Java side, you can create a DirectByteBuffer this way :
ByteBuffer directBuff = ByteBuffer.allocateDirect(sizeInBytes);
Think it as sort of C's malloc(sizeInBytes). Note: It has as automatic Cleaner, which deallocates the memory previously requested.
But there are some points to consider about using DirectByteBuffer:
It can be Garbage Collected (GC) if you miss your direct ByteBuffer reference.
You can read/write values to pointed structure, but beware with both offset and data size. Compiler may add extra spaces for padding and break your assumed internal offsets in structure. Structure with pointers (stride is 4 or 8 bytes ?) also puzzle your data.
Direct ByteBuffers are very easy to pass as a parameter for native methods, as well to get it back as return.
You must cast to correct pointer type at JNI side. Default type returned by env->GetDirectBufferAddress(buffer) is void*.
You are unable to change pointer value once created.
Its your job to free memory previously allocated for buffers at native side. That ones you used with env->NewDirectByteBuffer().
There is no good way. In SWT, this code is used:
int /*long*/ hModule = OS.GetLibraryHandle ();
and there is a tool which converts the code between 32bit and 64bit by moving the comment. Ugly but it works. Things would have been much easier if Sun had added an object "NativePointer" or something like that but they didn't.
A better way might by to store it in a byte array, since native pointers aren't very Java-ish in the first place. ints and longs are better reserved for storing numeric values.
I assume that this is a pointer returned from some JNI code and my advice would be just dont do it :)
Ideally the JNI code should pass you back some sort of logical reference to the resource and not an actual pointer ?
As to your question there is nothing that comes to mind about a cleaner way to store the pointer - if you know what you have then use either the int or long or byte[] as required.
You could look to the way C# handles this with the IntPtr type. By creating your own type for holding pointers, the same type can be used as a 32-bit or 64-bit depending on the system you're on.

Categories

Resources