When i run this demo it's call TestBean's writeObject method which is private
How is it possible ?
Here is the Code:
import java.io.FileOutputStream;
public class Test {
public static void main(String[] args) {
try {
TestBean testBean = test.new TestBean();
testBean.setSize(23);
testBean.setWidth(167);
FileOutputStream fos =
new FileOutputStream(new File("d:\\serial.txt"));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(testBean);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
class TestBean implements Serializable {
private static final long serialVersionUID = 1L;
private int size;
private int width;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
private void writeObject(ObjectOutputStream out) throws IOException {
System.out.println("TestBean writeObject");
out.defaultWriteObject();
}
private void readObject(ObjectInputStream input) throws IOException,
ClassNotFoundException {
System.out.println("TestBean readObject ===================> ");
input.defaultReadObject();
}
}
}
If your serializable object has any writeObject method, it will be called otherwise the defaultWriteObject method will be called.
The private method calling is possible using the reflection. If you see the source code of ObjectOutputStream Class in that method writeSerialData, the code below answers your question.
if (slotDesc.hasWriteObjectMethod()) {
// through reflection it will call the Serializable objects writeObject method
} else {
// the below is the same method called by defaultWriteObject method also.
writeSerialData(obj, desc);
}
The virtual machine will automatically check to see if either method
is declared during the corresponding method call. The virtual machine
can call private methods of your class whenever it wants but no other
objects can. Thus, the integrity of the class is maintained and the
serialization protocol can continue to work as normal. The
serialization protocol is always used the same way, by calling either
ObjectOutputStream.writeObject() or ObjectInputStream.readObject().
So, even though those specialized private methods are provided, the
object serialization works the same way as far as any calling object
is concerned.
You will get more about from this article:
Discover the secrets of the Java Serialization API
It uses reflection. private and public are not security measures. That is only a contract for class users.
Related
I need to use a native pointer (an int) for an LWJGL project, and the tutorial I'm following proposes to use the Object.finalize() method. But, since it's deprecated since Java 9, I looked for better solutions. I found the Cleaner/Cleanable duo on the Oracle documentation and tried to use it, but I don't know if I'm doing it right. Is this the way to go?
import java.lang.ref.Cleaner;
public class PointerUsingObject
{
// A native pointer
private int pointer;
private static final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
public PointerUsingObject()
{
cleanable = cleaner.register(this, new Runnable()
{
#Override
public void run()
{
// Free the pointer
}
});
}
// Is called to destroy the object when I'm sure not to use it anymore
public void destroy()
{
cleanable.clean();
}
}
OK, so as someone pointed out, I should instantiate a static nested class to manage the cleaning, as following:
import java.lang.ref.Cleaner;
public class PointerUsingObject implements AutoCloseable
{
// A native pointer
private int pointer;
private static final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
public PointerUsingObject()
{
cleanable = cleaner.register(this, new CleanMethod(pointer));
}
#Override
public void close() throws Exception
{
cleanable.clean();
}
private static class CleanMethod implements Runnable
{
private int pointer;
public CleanMethod(int pointer)
{
this.pointer = pointer;
}
#Override
public void run()
{
// Free the pointer
}
}
}
I also implemented the AutoCloseable interface and replaced the destroy() method with the close() method.
This question already has answers here:
What is the difference between Serializable and Externalizable in Java?
(11 answers)
Closed 4 years ago.
I'm learning about Serializable and Externalizable interface and I see that, when an Externalizable object is reconstructed, an instance is created first using the public no-arg constructor, then the readExternal method is called. If the object does not support Externalizable, then Serializable objects are restored by reading them from an ObjectInputStream.
I don't understand why we use ObjectInputStream for Externalization if the object isn't readed from there? What exactly is readed from the ObjectInputStream? I think we read something from there if we use it.
Also I found this chart about Deserialization Externalizable or Serializable interface
What is the difference between Serializable and Externalizable at the deserialization process?
I don't understand why the Externalizable objects aren't restored by reading them from an ObjectInputStream in the same way like Serializable objects?
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("employee.ser"))
I know that the FileInputStream opens a file, creates a sequence of bytes based on the data in the file. The ObjectInputStream takes a sequence of bytes, recreats the object based on the sequence of bytes.
And here is a code.
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class Employee implements Externalizable {
private int id;
private String name;
private int age;
public void Employee() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", age=" + age + "]";
}
public void writeExternal(ObjectOutput oo) throws IOException {
System.out.println("Inside writeExternal method");
oo.writeInt(id);
oo.writeObject(name);
}
public void readExternal(ObjectInput oi) throws IOException, ClassNotFoundException {
System.out.println("Inside readExternal method");
id = oi.readInt();
name = (String) oi.readObject();
}
}
ExternalizableWrite
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ExternalizableWrite {
public static void main(String args[]) {
ExternalizableWrite ew = new ExternalizableWrite();
ew.writeEmployeeObject();
}
private void writeEmployeeObject() {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("employee.ser"))) {
Employee employee = new Employee();
employee.setId(101);
employee.setName("Peter");
employee.setAge(25);
System.out.println(employee);
oos.writeObject(employee); // write the specified object to the ObjectOutputStream
System.out.println("Successfully written employee object to the file.\n");
} catch (FileNotFoundException ex) {
System.out.printf("ERROR: %s", ex);
} catch (IOException ex) {
System.out.printf("ERROR: %s", ex);
}
}
}
ExternalizableRead
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ExternalizableRead {
public static void main(String args[]) {
ExternalizableRead er = new ExternalizableRead();
er.readEmployeeObject();
}
private void readEmployeeObject() {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("employee.ser"))) {
Employee employee = (Employee) ois.readObject();
System.out.println(employee);
System.out.println("Successfully read employee objecct to the file.\n");
} catch (FileNotFoundException ex) {
System.out.printf("ERROR: %s", ex);
} catch (IOException | ClassNotFoundException ex) {
System.out.printf("ERROR: %s", ex);
}
}
}
What is the difference between Serializable and Externalizable at the deserialization process?
According to the implementation of ObjectInputStream, Externalizable objects are handled differently than Serializable objects, as expected:
if (desc.isExternalizable()) {
readExternalData((Externalizable) obj, desc);
} else {
readSerialData(obj, desc);
}
As you might expect, the readExternalData method calls Externalizable#readExternal for the object that is being deserialized, while the readSerialData method simply deserializes the serialized fields.
I don't understand why we use ObjectInputStream for Externalization if the object isn't readed from there?
I'm not sure what you're asking, but ObjectInputStream does handle Externalizable objects, as seen above.
I don't understand why the Externalizable objects aren't restored by reading them from an ObjectInputStream in the same way like Serializable objects?
Because Externalizable objects force you to manually serialize and deserialize them, whereas Serializable attempts to serialize all non-static and non-transient fields.
I don't understand why we use ObjectInputStream for Externalization if the object isn't readed from there?
Externalizable also uses ObjectInputStream.
ObjectInputStream is the parameter that is passed to the readExternal method. One may use methods such as readInt,readFloat etc of the ObjectInputStream to read the values from the serialized object.
What is the difference between Serializable and Externalizable at the deserialization process?
A class (implementing Serializable interface) can customize the data written the serialized object by using the following methods:
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
Suppose that there are classes A and B like this
class A implement Serializable {
writeObject(...){....}
readObject(...){....}
}
class B extends A implements Serializable{
writeObject(...){....}
readObject(...){....}
}
When an object of B is serialized/de-serialized then writeObject/readObject methods of parent/super class A is called before that of B, thus allowing for parent class' to decide which fields to serialize/de-serialize.
But, when it comes to Externalizable, this does not happen. Only sub-class's readExternal and writeExternal methods are called, overriding the parent's serialization/de-serialization behaviour.
I would like to save the data of an injected stateful bean at various intervals: change - save - change- save... I'm using core serialization and the problem is that all the byte arrays are the same. i believe the proxy is serialized because if I deserialize one of the arrays later I get the current state of the bean.
Example of serialization not capturing changes in the bean:
#Stateful
#RequestScoped
public class State implements Serializable {
private static final long serialVersionUID = 1L;
#Inject
StatelessBean bean; // assume it's needed
private List<String> list = new ArrayList<>();
public void add() {
list.add("S");
}
}
And this is a JAX-RS class:
#Stateless
#Path("t1")
public class ChickensResource {
#Inject
State state;
#GET
#Path("/test")
public String test() {
state.add();
byte[] b0 = serialize(state);
System.out.println(b0.length + " " + Arrays.toString(b0));
state.add();
byte[] b1 = serialize(state);
System.out.println(b1.length + " " + Arrays.toString(b1)); // prints same as b0
System.out.println(b0.length + " " + Arrays.toString(b0)); // prints same thing
}
public static <T extends Serializable> byte[] serialize(T s) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos))
{
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
What I want to do is only save the list in State as that's the relevant data. I also tried JSON serialization and it gave an IOException, but I'm trying core serialization.
Using JavaEE7 and Wildfly 10.1.
For various reasons, serializing a CDI bean directly is dangerous:
You may have a proxy, not the actual object; same holds true for the dependencies of that object
Serialization implies that the data will be deserialized at a time. But CDI beans are managed by CDI and CDI has no way to "attach" a deserialized object into its set of managed objects.
But the purpose of this question is to somehow save the state of a CDI bean in a way that it can be restored later. This can be accomplished by using another object that holds the state of the CDI bean. This other object is not managed by CDI, i.e. created with new, and is serializable. Each CDI bean that needs to persist its state has the pair of setState(state)/getState() methods - they could even be part of an interface. You probably want each object to propagate setState(state)/getState() to its collaborators too.
See the Memento design pattern. This is also implemented in the JSF state saving/restoring mechanism, if you are familiar with it.
Some example code (there are other valid ways to do it), starting with the state interface:
interface HasState<S extends Serializable> {
S getState();
void setState(S state);
}
Then the service itself, that has a collaborator, and the relevant state object:
class SomeServiceState implements Serializable {
private String someData;
private Long someId;
private List<String> list;
private CollaboratorState collaboratorState;
// accessors
}
#RequestScoped
public class SomeService implements HasState<SomeServiceState> {
// COLLABORATORS
#Inject
Collaborator collaborator; // assume it's needed
// INTERNAL STATE
private String someData;
private Long someId;
private List<String> list = new ArrayList<>();
public void add() {
list.add("S");
}
// ...
public SomeServiceState getState() {
SomeServiceState state = new SomeServiceState();
state.setSomeData(someData);
state.setSomeId(someId);
state.setList(new ArrayList<>(list)); // IT IS PROBABLY SAFER TO COPY STATE!
// SEE HOW STATE GETS EXTRACTED RECURSIVELY:
state.setCollaboratorState(collaborator.getState());
return state;
}
public void setState(SomeServiceState state) {
someData = state.getSomeData();
someId = state.getSomeId();
list = new ArrayList<>(state.getList());
// SEE HOW STATE GETS APPLIED RECURSIVELY:
collaborator.setState(state.getCollaboratorState());
}
}
The collaborator and its state follow the same pattern:
class CollaboratorState implements Serializable {
private String anyName;
// accessors
}
#RequestScoped
class Collaborator implements HasState<CollaboratorState> {
// you get the point...
}
And an example usage, following the code from the question:
#Stateless
#Path("t1")
public class ChickensResource {
#Inject
SomeService someService;
#GET
#Path("/test")
public String test() {
someService.add();
byte[] b0 = serialize(someService.getState());
// ...
}
public static <T extends Serializable> byte[] serialize(T s) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos))
{
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
EDIT: If the client of a service needs to know that a service has state, then the client and service might be more coupled than it would be desired. A way out is to modify HasState to deal with opaque objects:
interface HasState {
Object getState();
void setState(Object state);
}
The state of the client contains a list for the state of each collaborator:
class SomeServiceState implements Serializable {
private String someData;
private Long someId;
private List<String> list;
private List<Object> collaboratorsState;
// accessors
}
The client adds a collaborator to the state only if it extends HasState:
public Object getState() {
SomeServiceState state = new SomeServiceState();
state.setSomeData(someData);
state.setSomeId(someId);
state.setList(new ArrayList<>(list));
if( collaborator instanceof HasState ) {
state.getCollaboratorsState().add(collaborator.getState());
}
return state;
}
I'm trying to serialize this Configuration object, but for the life of me I can't get it. I've checked everywhere including StackOverflow. Any help would be greatly appreciated.
Serialization Code:
public void serialize(String outFile)
throws IOException {
Configuration config = new Configuration().getConfiguration();
System.out.println(config.email);
try
{
FileOutputStream outputFile =
new FileOutputStream("/home/jason/Desktop/config.ser");
ObjectOutputStream objectOutput = new ObjectOutputStream(outputFile);
objectOutput.writeObject(config);
objectOutput.close();
outputFile.close();
}catch(IOException i)
{
i.printStackTrace();
}
System.out.println(config);
}
public void deSerialize()
throws FileNotFoundException, IOException, ClassNotFoundException {
Configuration config = new Configuration().getConfiguration();
try
{
FileInputStream inputFile = new FileInputStream("/home/jason/Desktop/config.ser");
ObjectInputStream objectInput = new ObjectInputStream(inputFile);
config = (Configuration) objectInput.readObject();
config.setConfiguration(config);
objectInput.close();
inputFile.close();
}catch(Exception e)
{
e.printStackTrace();
}
System.out.println(config);
}
And then I call it with the following code:
DataStore data = new DataStore().getInstance();
try {
data.deSerialize();
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
DataStore is a simple singleton, and takes no input parameters. It doesn't have any real variables, but simply employs the serialization functions.
Finally, here is my Configuration code:
public class Configuration implements Serializable{
private static final long serialVersionUID = 1388190376766023647L;
public static String email = "";
private static String ip = "";
private static String password = "";
private static String importNumber;
private static Configuration configuration;
private static int singleton = 0;
public String value_of_da_message;
public Configuration()
{}
public Configuration getConfiguration()
{
if(singleton == 0){
configuration = new Configuration();
singleton++;
return configuration;
}
else
return configuration;
}
public void setConfiguration(Configuration config)
{
configuration = config;
}
Any clue on where I'm going wrong? Thanks for the help.
Have a look here: Java static serialization rules?
Change your fields to be instance fields, which would better fit the singleton approach anyways.
The fields might be serialized but deserialization normally ignores static fields.
Additionally, it looks like you're reading to the temporary object:
config.setConfiguration(config);
This uses the read object twice and doesn't set the data of the singleton unless you keep that a static field (i.e. configuration in the Configuration class is the reference to the singleton and needs to be static)
Update:
Another hint: the static variable singleton might cause problems and is unneeded anyway. Just check configuration == null instead of singleton == 0.
Hint:
I try to help you with serialization in general, but in your special case you might want to use Properties instead which have built-in serialization features (.properties- and xml-files supported) and which are meant for configuration.
I have this class in Java (it's from JaCoCo Project):
public class MemoryMultiReportOutput implements IMultiReportOutput {
private final Map<String, ByteArrayOutputStream> files = new HashMap<String, ByteArrayOutputStream>();
private final Set<String> open = new HashSet<String>();
private boolean closed = false;
public OutputStream createFile(final String path) throws IOException {
assertFalse("Duplicate output " + path, files.containsKey(path));
open.add(path);
final ByteArrayOutputStream out = new ByteArrayOutputStream() {
#Override
public void close() throws IOException {
open.remove(path);
super.close();
}
};
files.put(path, out);
return out;
}
public void close() throws IOException {
closed = true;
}
public void assertEmpty() {
assertEquals(Collections.emptySet(), files.keySet());
}
public void assertFile(String path) {
assertNotNull(String.format("Missing file %s. Actual files are %s.",
path, files.keySet()), files.get(path));
}
public void assertSingleFile(String path) {
assertEquals(Collections.singleton(path), files.keySet());
}
public byte[] getFile(String path) {
assertFile(path);
return files.get(path).toByteArray();
}
public InputStream getFileAsStream(String path) {
return new ByteArrayInputStream(getFile(path));
}
public void assertAllClosed() {
assertEquals(Collections.emptySet(), open);
assertTrue(closed);
}
}
When I compile this class the Eclipse create MemoryMultiReportOutput.class and MemoryMultiReportOutput$1.class.
First question: Why Eclipse create the MemoryMultiReportOutput$1.class? Eclipse considers the ByteArrayOutputStream out a InnerClass?
But my problem is, when I load the MemoryMultiReportOutput.class how can I load the all innerclasses present in parent class?
To answer your first question:
final ByteArrayOutputStream out = new ByteArrayOutputStream() {
#Override
public void close() throws IOException {
open.remove(path);
super.close();
}
};
Here you are creating a subclass of the ByteArrayOutputStream on the fly, i.e anonymous. This is why you have another .class file.
To answer your second question:
You can only load parent inner classes, visible to the subclass, through the Superclass's instance object :
Superclass s = new Superclass();
Superclass.Subclass sub = s.new Subclass();
If the inner class is static i.e a top-level nested class (since there is no such thing as inner static class) can be instantiated like this:
Superclass.Subclass s = new Superclass.Subclass();
and it does not require an object instance of the superclass.
Hope this helps!
Your creating an anonymous inner class with the
new ByteArrayOutputStream()
That's why you see the MemoryMultiReportOutput$1.class file.
You don't need to do anything to load the inner classes. That will happen automatically.
If your asking how to access the inner class from another class that's a bit different. You would need to mark it public or provide an accessor that would return an instance of the class. Is that what you were asking?