PhysicsThread.java starts a new thread. The run method executes the initialize method. This method creates the physics world. After that, it starts a while loop that updates the world with an interval of 1000/60 = 16 milliseconds. However, I get a nullpointerexception in the loop, because it does not always know world, even though I check for that. Can explain what is happening?
PhysicsThread.java
public class PhysicsThread implements Runnable {
long fps = 60;
DiscreteDynamicsWorld dw;
long lasttime = System.currentTimeMillis();;
static int maxPhysicsObjects = 50000;
PhysicsThread() {
Thread t = new Thread(this);
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
@Override
public void run() {
System.out.println("Start thread");
init();
System.out.println("Start threadloop");
while(true) {
loop();
}
}
public void init() {
BroadphaseInterface broadphase = new AxisSweep3_32(new Vector3f(0,0,0), new Vector3f(200000,200000,200000), maxPhysicsObjects);//new DbvtBroadphase();
DefaultCollisionConfiguration collisionConfiguration = new DefaultCollisionConfiguration();
CollisionDispatcher dispatcher = new CollisionDispatcher(
collisionConfiguration);
SequentialImpulseConstraintSolver solver = new SequentialImpulseConstraintSolver();
dw = new DiscreteDynamicsWorld(dispatcher, broadphase,
solver, collisionConfiguration);
System.out.println("Made world");
dw.setGravity(new Vector3f(0, 0, -10));
}
public void loop() {
if (dw!=null) {
float delta = System.currentTimeMillis()-lasttime;
lasttime = System.currentTimeMillis();
dw.stepSimulation(delta/1000f, 1, 1/60f);
}
try {
Thread.sleep(1000/fps);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public DiscreteDynamicsWorld getWorld() {
return dw;
}
}
I suspect this may be down to your construction technique, which is an antipattern. You shouldn’t let the
thisreference “escape” during a constructor, because then other threads may see the object in a partially-constructed state. At this point, all bets are off about the state of the class, and even invariants that are always true (such as final fields being set to a value) may not hold.I wonder if what is happening here might be due to the following sequence of events:
this.init(settingdw), and half ofloop, before being pre-empted.dwtonullas part of field initialisation.deltaandlastTime, then sees a null value fordw.I’m a little hesistant to say that’s exactly the case because I would have expected the fields to be initialised before the constructor body runs. However it seems likely that accessing the fields while the object is still being constructed is a very bad idea.
In order to fix this I’d suggest not starting a thread in the constructor, but rather having the calling code start the thread afterwards, e.g.:
(Also, the idea of having
initmethods that aren’t the constructor is usually a bad idea – if thedwfield never changes, why not perform all the work ofinitduring the constructor itself and markdwasfinal? This will be cleaner and make your code easier to reason about, since the VM guarantees the value will be fully set during construction and that it will never change afterwards. The only downside is a performance hit if you construct lots of these instances and never actually run them – so just don’t do that. 🙂Plus the class name is misleading, since this isn’t a
Threadbut aRunnable. Calling it something likePhysicsTaskorPhysicsSimulationRunwould arguably be clearer.)