I’m guessing you’re familiar with this, but just in case, Object.finalize() was deprecated in JDK 9. So far as I know it still works as expected, but it may eventually stop working or be removed entirely.
You can never access the referent because then the Reference’s state becomes invalid. Suddenly you’d have a strong reference to the object again.
…which is why to me the difference between the reference subclasses is largely academic in most cases.
To me, essentially these are the reasons based on my understanding:
WeakReference - you need to do something before finalize is run.
SoftReference - you want to hold onto the object until memory is running out
PhantomReference - you want to keep the object in memory until you specifically clear it
For most people “I want to clean things up when the object is ready to be garbage collected” = WeakReference. The use-cases for the others are pretty specific and narrow.
That was a very interesting article. In all my years using java I was also not aware of WeakReferences and PhantomReferences until you started talking about them here. Granted, I knew of the finalize method, but have never used it in an application. I guess I have been working mostly on applications that I would never run across use cases for this stuff until JME.
I ran some experiments this morning using a simple test app.
It seems that if the referent overrides finalize()
and the metadata class extends PhantomReference
, then the metadata never gets queued. On the other hand, if the metadata extends WeakReference
, then it gets queued even if the referent overrides finalize()
.
So until I can eliminate finalize()
completely, I’d better use WeakReference
.
All of Minie’s finalize()
methods have been eliminated, by:
- writing additional native code to avoid issue 1351
- splitting up several classes that contained multiple native objects
- adding the
static
qualifier to allfinalizeNative()
methods (and hundreds of other native methods as well) - tracking native objects using
WeakReference
, and - adding a “Physics Cleaner” daemon thread.
All the changes are committed, and I think they turned out OK. The source code is generally simpler and clearer than it was before, with plenty of assertions. However, a lot got changed, and much of it is rarely used and/or tricky to test. (For example, many of the sample apps don’t run long enough to need garbage collection, and the daemon thread doesn’t run during unit tests.) So I plan to give Minie a couple weeks of “soak time” before releasing v2.
I’ve added a tutorial on rigid-body physics.
Anticipating that the Minie tutorials might someday be included in the JMonkeyEngine Wiki, I’ve begun converting them from Markdown to Antora/Asciidoc.
Once that’s done, I plan to write more automated tests and enhance DacWizard and the example apps. The enhancements to debug visualization are still planned for v2.0.
Not sure if you know, but there are tools that can automate conversion from markdown to asciidoc.
I had a hunch there might be. Do they do a good job?
Edit: Most of my time has been spent
- figuring out how to use Antora with GitHub Pages and
- how to organize my Antora sources in such as way that the tutorials can be shared between Minie and the JMonkeyEngine wiki.
Besides, I need to learn asciidoc so I can be effective creating new content.
Yeah, I’ve done a few conversions with pandoc, which seems to be the go-to for doc conversions. Github flavor markdown → asciidoc (should end up as .adoc files). There’s differences in the different markdown flavors, make sure you know what type your input is. Github actually displays .adoc files just fine, like your github flavor markdown files would look.
Debug visualization can now handle local physics. I added a setTransformSpatial()
method to BulletAppState
, to specify the transform, if any, between physics space and scene/world space.
The tutorials still have a lot of gaps. Plugging those gaps could keep be busy for a while…
It occured to me that Minie ought to include some examples that use an entity system such as Zay-ES. Maybe even a tutorial.
There’s the SiO2-bullet extension - its pretty easy to convert that to Minie, but examples would be great.
@sgold is there a double precision Minie library distributed now? (just read the top post)
Yes. For production use implementation 'com.github.stephengold:Minie:1.7.0+dp'
and for debugging use implementation 'com.github.stephengold:Minie:1.7.0+debugdp'
A difficult-to-reproduce issue held up the Minie v2.0 release for several weeks. Said issue appears to be resolved. I currently expect to release v2.0 next week.
This is really great news since this exception is happening all the time in my product. I found a way to bypass it but it cost me in omitting a few features.
I will immediately know if this fix resolved my crash and report back
I had no idea you were testing v2!
I’m waiting for the release of V2.0 next week
Minie issue 9 occurs ONLY in v2. If you’re seeing exceptions with v1.7 or earlier, then that’s a different issue, and I’d like to see a stack trace.
Well… real strange. I can see the crash is happening in bulletjme.dll but I’m not using it. I’m using Minie v1.7.
When I start running my project I can see that bulletjme.dll is created in the root folder. But I can’t see which module of my project holding reference to the old bullet jars…
I need to further investigate it
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffc26020baa, pid=7984, tid=8692
#
# JRE version: Java(TM) SE Runtime Environment (8.0_45-b14) (build 1.8.0_45-b14)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.45-b02 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [bulletjme.dll+0x90baa]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
--------------- T H R E A D ---------------
Current thread (0x00000000025a4800): JavaThread "Finalizer" daemon [_thread_in_native, id=8692, stack(0x0000000015ee0000,0x0000000015fe0000)]
siginfo: ExceptionCode=0xc0000005, reading address 0x0000000000000120
Registers:
RAX=0x0000000000000000, RBX=0x000000003a329ea8, RCX=0x0000000000000000, RDX=0x0000000015fdf128
RSP=0x0000000015fdf028, RBP=0x0000000015fdf0f8, RSI=0x0000000000001ff0, RDI=0x00000000c0c8e6f0
R8 =0x0000000000000000, R9 =0x00000000eaeddf90, R10=0x00000000025c5e08, R11=0x0000000069457ca0
R12=0x0000000000000000, R13=0x000000003a329ea8, R14=0x0000000015fdf128, R15=0x00000000025a4800
RIP=0x00007ffc26020baa, EFLAGS=0x0000000000010206
Top of Stack: (sp=0x0000000015fdf028)
0x0000000015fdf028: 00007ffc26052f47 0000000000000000
0x0000000015fdf038: 00007ffc54c9fb91 0000000000000018
0x0000000015fdf048: 00000000005c0000 0000000000000000
0x0000000015fdf058: 0000000015fdf218 000000003a957e38
0x0000000015fdf068: 0000000000000000 00000000327dc7c0
0x0000000015fdf078: 00000000025c5e34 00000000025a49f8
0x0000000015fdf088: 0000000015fdf128 0000000000000000
0x0000000015fdf098: 0000000000000000 0000000000000000
0x0000000015fdf0a8: 00007ffc260f562f 00000000c0c8e7a8
0x0000000015fdf0b8: 0000000015fdf0b8 0000000000000000
0x0000000015fdf0c8: 0000000015fdf128 000000003a940de8
0x0000000015fdf0d8: 0000000000000000 000000003a329ea8
0x0000000015fdf0e8: 0000000000000000 0000000015fdf118
0x0000000015fdf0f8: 0000000015fdf170 00000000025b7800
0x0000000015fdf108: 0000000000000000 00000000025bf977
0x0000000015fdf118: 0000000000000000 00000000025b7800
Instructions: (pc=0x00007ffc26020baa)
0x00007ffc26020b8a: 40 10 48 83 c4 28 c3 cc cc cc cc cc cc cc cc cc
0x00007ffc26020b9a: cc cc cc cc cc cc 48 89 4c 24 08 48 8b 44 24 08
0x00007ffc26020baa: 48 8b 80 20 01 00 00 c3 cc cc cc cc cc cc cc cc
0x00007ffc26020bba: cc cc cc cc cc cc 44 88 4c 24 20 4c 89 44 24 18
Register to memory mapping:
RAX=0x0000000000000000 is an unknown value
RBX={method} {0x000000003a329eb0} 'getSpaceId' '(J)J' in 'com/jme3/bullet/collision/PhysicsCollisionObject'
RCX=0x0000000000000000 is an unknown value
RDX=0x0000000015fdf128 is pointing into the stack for thread: 0x00000000025a4800
RSP=0x0000000015fdf028 is pointing into the stack for thread: 0x00000000025a4800
RBP=0x0000000015fdf0f8 is pointing into the stack for thread: 0x00000000025a4800
RSI=0x0000000000001ff0 is an unknown value
RDI=0x00000000c0c8e6f0 is an oop
com.scenemaxeng.projector.CollisionListener
- klass: 'com/scenemaxeng/projector/CollisionListener'
R8 =0x0000000000000000 is an unknown value
R9 =0x00000000eaeddf90 is an oop
java.lang.String
- klass: 'java/lang/String'
R10=0x00000000025c5e08 is at code_begin+840 in an Interpreter codelet
method entry point (kind = native) [0x00000000025c5ac0, 0x00000000025c6420] 2400 bytes
R11=0x0000000069457ca0 is an unknown value
R12=0x0000000000000000 is an unknown value
R13={method} {0x000000003a329eb0} 'getSpaceId' '(J)J' in 'com/jme3/bullet/collision/PhysicsCollisionObject'
R14=0x0000000015fdf128 is pointing into the stack for thread: 0x00000000025a4800
R15=0x00000000025a4800 is a thread
Stack: [0x0000000015ee0000,0x0000000015fe0000], sp=0x0000000015fdf028, free space=1020k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [bulletjme.dll+0x90baa]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j com.jme3.bullet.collision.PhysicsCollisionObject.getSpaceId(J)J+0
j com.jme3.bullet.collision.PhysicsCollisionObject.spaceId()J+7
j com.jme3.bullet.collision.PhysicsCollisionObject.getCollisionSpace()Lcom/jme3/bullet/CollisionSpace;+3
j com.jme3.bullet.collision.PhysicsCollisionObject.finalize()V+13
J 1904 C1 java.lang.ref.Finalizer.runFinalizer(Lsun/misc/JavaLangAccess;)V (62 bytes) @ 0x0000000002bec90c [0x0000000002bec380+0x58c]
J 1903 C1 java.lang.ref.Finalizer.access$100(Ljava/lang/ref/Finalizer;Lsun/misc/JavaLangAccess;)V (6 bytes) @ 0x0000000002bed6dc [0x0000000002bed680+0x5c]
j java.lang.ref.Finalizer$FinalizerThread.run()V+45
v ~StubRoutines::call_stub