public static void main(String[] args) {
Chatter chatter = new Chatter();
String text = "Hello " + chatter.getWord() + "!";
System.out.println(text);
free text; // destroy object and reclaim the memory
free chatter; // destroy object and reclaim the memory
// System.out.println(chatter); // use after free NEVER compiles
}
}// OR:
public class Hello {
public static void main(String[] args) {
Chatter chatter = new Chatter();
defer free chatter;
String text = "Hello " + chatter.getWord() + "!";
defer free text;
System.out.println(text);
}
}This is difficult in the general case, but Ironwood makes it tractable through ahead-of-time compilation, a closed world of reachable code, and conservative method summaries. It does not need to infer every object’s lifetime perfectly. It only needs to prove that each explicit free is safe.
If aliases, call effects, or control flow make that proof uncertain, the compiler rejects the free. The programmer must then restructure the code or omit free, in which case the allocation remains until process termination. This is intended as the conservative fallback, not the normal outcome for straightforward, compiler-provable ownership patterns.
After an accepted free, any later use is also rejected. This approach may increase compilation work, but it provides memory safety without runtime ownership tracking.