"NegativeArraySizeException" - Custom Class Loader - java

I had a class loader working although I am now getting an error after adapting it to my new application. I believe it is because I am converting an integer to a long.
private byte[] loadClassData(String name) {
try {
JarInputStream jis = new JarInputStream(new ByteArrayInputStream(dec));
JarEntry entry = null;
String entryName = null;
while((entry = jis.getNextJarEntry()) != null)
{
entryName = entry.getName();
if(entryName.equalsIgnoreCase(name))
{
try{
classBytes = new byte[(int)entry.getSize()];
jis.read(classBytes, 0, classBytes.length);
return classBytes;
}catch(Exception ex){
ex.printStackTrace();
return null;
}
}
}
return classBytes;
} catch (IOException e) {
e.printStackTrace();
System.out.println(e.getMessage());
} catch (Exception ex) {
ex.printStackTrace();
System.out.println(ex.getMessage());
}
return null;
}
Anyways, that is the basics of it. I am getting an error on the " new byte[(int)entry.getSize()];" part.
"java.lang.NegativeArraySizeException"
Thanks.

Yes, because ZipEntry.getSize() can return -1. Even if it didn't return -1, you shouldn't assume that a single call to read will read all the data. You should read in a loop until the input stream returns -1.
I suggest you use ByteStreams.toByteArray(InputStream) from Guava for this.

Related

How do I releasing resources for fileinputstream and fileoutstream?

In my veracode scan, I have very low vulnerability: Improper Resource Shutdown or Release CWE ID 404
And here is my code:
public static boolean nioCopy(File source, File destination) {
boolean retval = false;
FileChannel inChannel = null, outChannel = null;
try {
inChannel = (new FileInputStream(source)).getChannel();
outChannel = (new FileOutputStream(destination)).getChannel();
long size = inChannel.size();
long position = 0;
while ( position < size )
{
position += inChannel.transferTo( position, WINDOWS_MAGIC_BUFFER_SIZE, outChannel );
}
retval = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
retval = false;
} catch (IOException e) {
e.printStackTrace();
retval = false;
} finally {
try {
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return retval;
}
Veracode is specifically pointing to this line:
outChannel = (new FileOutputStream(destination)).getChannel();
However, I believe I am releasing the resource in finally block. I was referring to this link: http://javaelegance.blogspot.com/2015/10/improper-resource-shutdown-or-release.html
What am I doing wrong here?
Assuming Java 8 or higher, use try with resources statements. See https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html. It basically will handle automatically closing closable objects for you.
try (inChannel = (new FileInputStream(source)).getChannel()) {
//Use inChannel
}
catch(IOException ex) {
//Handle exception
}

Java InputStream with different Object Classes

my code has to read in two different Object Types (Bestellung, AKunde) through a ObjectOutputStream and save it in a csv file, which works.
But when i try to read them from the file it doesn't work.
Here is the code:
OutputStream:
LinkedList<Bestellung> bestellListe = verwaltungBestell.getBestellListe();
try {
fileOutputStream = new FileOutputStream(file);
outputStream = new ObjectOutputStream(fileOutputStream);
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
InputStream:
ArrayList<AKunde> kundenImport = new ArrayList<AKunde>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<Bestellung>();
boolean cont = true;
try {
ObjectInputStream objectStream = new ObjectInputStream(new FileInputStream(directorie));
while (cont) {
AKunde kunde = null;
try {
kunde = (AKunde) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (kunde != null) {
kundenImport.add(kunde);
} else {
cont = false;
}
}
while (cont) {
Bestellung bestellung = null;
try {
bestellung = (Bestellung) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (bestellung != null) {
bestellungenImport.add(bestellung);
} else {
cont = false;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
}
But it won't read the "Bestellungen" and won't save them into "bestellungenImport".
Anyone has a solution???
Your code never reaches the Bestellung reader part.
You have a false assumption that kunde =(AKunde)objectStream.readObject(); returns null.
Instead, it throws exception.
Oneway you can do is cast it like #luk2302.
Another way is to add a object count when writing your object stream:
outputStream.writeInt(kundenliste.size());
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
outputStream.writeInt(bestellListe.size());
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
Then replace your while(cont) loop with a for each loop:
int kundeCount = objectStream.readInt();
for (int i = 0; i < kundeCount; i++) {
// Read and import kunde
}
You need to change your logic for reading objects. There are two main issues:
you never reset cont so the second while loop will never do anything
even if you did that you would always skip the first Bestellung since it was already read when the second loop is reached
I would propose something along the lines of:
Object object = objectStream.readObject();
if (object instanceof AKunde) {
kundenImport.add((AKunde) object);
} else if (object instanceof Bestellung) {
bestellungenImport.add((Bestellung) object);
} else {
// something else was read
}
You simply need to loop over this code and add proper error handling where needed.
I would suggest, you change the way you write your objects to ObjectOutputStream in the first place:
Directly write the kundenListe and bestellListe objects, so you dont't have to worry about types or number of elements when reading the objects again. Your stream of object then always contains two objects, the two lists.
// use try-with-resources if you're on Java 7 or newer
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file))) {
// write the complete list of objects
outputStream.writeObject(kundenliste);
outputStream.writeObject(bestellListe);
} catch (IOException e) {
e.printStackTrace(); //TODO proper exception handling
}
Then you could read it just like that:
ArrayList<AKunde> kundenImport = new ArrayList<>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<>();
//again try-with-resources
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file))) {
kundenImport.addAll((List) inputStream.readObject());
bestellungenImport.addAll((List) inputStream.readObject());
} catch (IOException | ClassNotFoundException e) { //multi-catch, if Java 7 or newer
e.printStackTrace(); //TODO proper exception handling
}
Further reads:
The try-with-resources Statement
Catching Multiple Exception Types (...)

Java serialize overwrite the current file

Currently I'm serializing an ArrayList to a file like this:
FileOutputStream fosAlarms = null;
ObjectOutputStream oosAlarms = null;
try {
fosAlarms = openFileOutput("alarms.ser", Context.MODE_PRIVATE);
oosAlarms = new ObjectOutputStream(fosAlarms);
oosAlarms.writeObject(alarms);
System.out.println("Serialisation done");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (oosAlarms != null && fosAlarms != null) {
try {
oosAlarms.close();
fosAlarms.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And this works as intended. But I want this method to overwrite current file (if there is any). If I remove an object from the array and serialize it again, the removed object persists. How do I do this?
Use this constructor of FileOutputStream and set append to false.
FileOutputStream(String, boolean)
So... I guess you need to change a bit your method openFileOutput.

Decide cast and return type by Parameter

I really don't know what to look for and if this is even possible. I am trying to code a dynamic Fileloader.
This is the code:
public static Serializable loadSerializable(Context context,
String filename, Object object) {
final String DEBUGTAG = "Loading data" ;
Serializable serializable = null;
ObjectInputStream oin = null;
try {
File file = new File(context.getFilesDir(), filename);
FileInputStream in = new FileInputStream(file);
oin = new ObjectInputStream(in);
Object readElement = oin.readObject();
serializable = (Serializable) readElement; // here I want dynamic casting
Log.d(DEBUGTAG, "Success : " + filename);
} catch (FileNotFoundException e) {
Log.d(DEBUGTAG, "File not found");
} catch (StreamCorruptedException e) {
Log.d(DEBUGTAG, "Stream Corrupted");
} catch (IOException e) {
Log.d(DEBUGTAG, "IOException");
} catch (ClassNotFoundException e) {
Log.d(DEBUGTAG, "Class not Found");
} catch (NullPointerException e) {
Log.d(DEBUGTAG, "NullPointer - File does not exist yet");
} finally {
if (oin != null)
try {
oin.close();
} catch (IOException e) {
Log.d(DEBUGTAG, "IOException - Stream not closed");
}
}
return serializable;
}
What I want to do now is instead of creating a new method for every single object I want to use the 3rd argument (object or whatever) for the type casting.
So I could write
String myString = loadSerializable(this, test.dat, String) or
ArrayList<Fragment> = loadSerializable(this, test.dat, ArrayList<Fragment>) and so on....
Help appreciated
Something like
public static <T> T loadSerializable(Context context, String filename) {
// ...
T t = (T) readElement;
// ...
return t;
}

Deserialize multiple Java Objects

hello dear colleagues,
I have a Garden class in which I serialize and deserialize multiple Plant class objects. The serializing is working but the deserializing is not working if a want to assign it to calling variable in the mein static method.
public void searilizePlant(ArrayList<Plant> _plants) {
try {
FileOutputStream fileOut = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
for (int i = 0; i < _plants.size(); i++) {
out.writeObject(_plants.get(i));
}
out.close();
fileOut.close();
} catch (IOException ex) {
}
}
deserializing code:
public ArrayList<Plant> desearilizePlant() {
ArrayList<Plant> plants = new ArrayList<Plant>();
Plant _plant = null;
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
Object object = in.readObject();
// _plant = (Plant) object;
// TODO: ITERATE OVER THE WHOLE STREAM
while (object != null) {
plants.add((Plant) object);
object = in.readObject();
}
in.close();
} catch (IOException i) {
return null;
} catch (ClassNotFoundException c) {
System.out.println("Employee class not found");
return null;
}
return plants;
}
My invoking code:
ArrayList<Plant> plants = new ArrayList<Plant>();
plants.add(plant1);
Garden garden = new Garden();
garden.searilizePlant(plants);
// THIS IS THE PROBLEM HERE
ArrayList<Plant> dp = new ArrayList<Plant>();
dp = garden.desearilizePlant();
edit
I got a null Pointer exception
The solution of #NilsH is working fine, thanks!
How about serializing the entire list instead? There's no need to serialize each individual object in a list.
public void searilizePlant(ArrayList<Plant> _plants) {
try {
FileOutputStream fileOut = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(_plants);
out.close();
fileOut.close();
} catch (IOException ex) {
}
}
public List<Plant> deserializePlant() {
List<Plants> plants = null;
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
plants = in.readObject();
in.close();
}
catch(Exception e) {}
return plants;
}
If that does not solve your problem, please post more details about your error.
It may not always be feasible to deserialize a whole list of objects (e.g., due to memory issues). In that case try:
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
filename));
while (true) {
try {
MyObject o = (MyObject) in.readObject();
// Do something with the object
} catch (EOFException e) {
break;
}
}
in.close();
Or using the Java SE 7 try-with-resources statement:
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(
filename))) {
while (true) {
MyObject o = (MyObject) in.readObject();
// Do something with the object
}
} catch (EOFException e) {
return;
}
If you serialize it to an array linear list, you can cast it back to an array linear list when deserializing it -- all other methods failed for me:
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
public class Program
{
public static void writeToFile(String fileName, Object obj, Boolean appendToFile) throws Exception
{
FileOutputStream fs = null;
ObjectOutputStream os = null;
try
{
fs = new FileOutputStream(fileName);
os = new ObjectOutputStream(fs);
//ObjectOutputStream.writeObject(object) inherently writes binary
os.writeObject(obj); //this does not use .toString() & if you did, the read in would fail
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
os.close();
fs.close();
}
catch(Exception e)
{
//if this fails, it's probably open, so just do nothing
}
}
}
#SuppressWarnings("unchecked")
public static ArrayList<Person> readFromFile(String fileName)
{
FileInputStream fi = null;
ObjectInputStream os = null;
ArrayList<Person> peopleList = null;
try
{
fi = new FileInputStream(fileName);
os = new ObjectInputStream(fi);
peopleList = ((ArrayList<Person>)os.readObject());
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch(EOFException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
os.close();
fi.close();
}
catch(Exception e)
{
//if this fails, it's probably open, so just do nothing
}
}
return peopleList;
}
public static void main(String[] args)
{
Person[] people = { new Person(1, 39, "Coleson"), new Person(2, 37, "May") };
ArrayList<Person> peopleList = new ArrayList<Person>(Arrays.asList(people));
System.out.println("Trying to write serializable object array: ");
for(Person p : people)
{
System.out.println(p);
}
System.out.println(" to binary file");
try
{
//writeToFile("output.bin", people, false); //serializes to file either way
writeToFile("output.bin", peopleList, false); //but only successfully read back in using single cast
} // peopleList = (ArrayList<Person>)os.readObject();
// Person[] people = (Person[])os.readObject(); did not work
// trying to read one at a time did not work either (not even the 1st object)
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("\r\n");
System.out.println("Trying to read object from file. ");
ArrayList<Person> foundPeople = null;
try
{
foundPeople = readFromFile("input.bin");
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (foundPeople == null)
{
System.out.println("got null, hummm...");
}
else
{
System.out.println("found: ");
for(int i = 0; i < foundPeople.size(); i++)
{
System.out.println(foundPeople.get(i));
}
//System.out.println(foundPeople); //implicitly calls .toString()
}
}
}

Categories

Resources