79206760

Date: 2024-11-20 10:24:01
Score: 0.5
Natty:
Report link

I tried following options:

  1. Retrieving the seed via reflection as stated in the linked answer does not work for me (yielding a java.lang.reflect.InaccessibleObjectException)
  2. Creating a new prng with the same seed and progressing it to the same state
  3. Serializing, (saving & loading), de-serializing the same object

For me, the 1st option seems to be the most problematic, relying on implementation specifics. The 2nd option is not elegant in that it wastes computing time. The 3rd option seems to be the closest to my requirements.

Following I attach my test source-code for anyone running into the same requirements:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

public class PrngSaveLoadTest {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        long initialSeed = 4;
        final Random prng1 = new Random(initialSeed);
        int amountOfSteps = 0;
        // Generate arbitrary amount of random numbers
        for (int i = 1; i <= 21; i++) {
            prng1.nextInt();
            amountOfSteps++;
        }
        // TODO: Save state
        // TODO: Load state later, continuing with the same random numbers as if it were the same random number generator

        // Option 1: Use reflection to get internal seed of prng1 - does not work, throws exception
        //final Random prngRestoredBySeed = new Random(getSeed(prng1));
        //System.out.println("Should be identical: " + prng1.nextInt() + " =!= " + prngRestoredBySeed.nextInt());

        // Option 2: Progress the second prng instance the same amount of numbers - works
        final Random prngRestoredByProgress = new Random(initialSeed);
        progressPrng(prngRestoredByProgress, amountOfSteps);
        System.out.println("Should be identical: " + prng1.nextInt() + " =!= " + prngRestoredByProgress.nextInt());

        // Option 3: Serialize, save, load, deserialize the prng instance
        byte[] serializedPrng = serializePrng(prng1);
        Random prngRestoredBySerialization = deserializePrng(serializedPrng);
        System.out.println("Should be identical: " + prng1.nextInt() + " =!= " + prngRestoredBySerialization.nextInt());

    }

    /**
     * See https://stackoverflow.com/a/29278559/1877010
     */
    private static long getSeed(Random prng) throws NoSuchFieldException, IllegalAccessException {
        long theSeed;
        try {
            Field field = Random.class.getDeclaredField("seed");
            field.setAccessible(true);
            AtomicLong scrambledSeed = (AtomicLong) field.get(prng);   //this needs to be XOR'd with 0x5DEECE66DL
            theSeed = scrambledSeed.get();
            return (theSeed ^ 0x5DEECE66DL);
        } catch (Exception e) {
            //handle exception
            throw e;
        }
    }

    private static void progressPrng(Random prng, long amountOfSteps) {
        for (long i = 1; i <= amountOfSteps; i++) {
            prng.nextInt();
        }
    }

    private static byte[] serializePrng(Random prng) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream(128);
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(prng);
            return baos.toByteArray();
        }
    }

    private static Random deserializePrng(byte[] serializedPrng) throws IOException, ClassNotFoundException {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(serializedPrng);
             ObjectInputStream in = new ObjectInputStream(bais)) {
            // Method for deserialization of object
            return ((Random) in.readObject());
        }
    }
}
Reasons:
  • Blacklisted phrase (1): stackoverflow
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: DaHoC