-
Sub-task
-
Resolution: Delivered
-
P4
-
24
Refactoring `javac` to support JEP 492 exposed some existing problems regarding local classes and static contexts. For example:
```
class O {
static void foo(int x) {
class C { // in static context, so no enclosing instance
void outer() {
System.out.println(x); // capture x
}
}
class U {
static void test() {
new C(); // (a)
}
}
}
public static void main(String[] args) {
foo(42);
}
}
```
`javac` 23 compiles this program, but executing the classfile for class O throws an internal exception trying to create the instance at position (a).
`javac` 24 requires that any new expression creating an instance of a class C where C is an inner local class that appears in a static context, should appear in the same static context. Thus the new expression at position (a) results in a compile-time error.
There is a similar fix for new expressions that create instances of anonymous classes, that is, new expressions with class bodies.
A similar issue surrounds super constructor invocations in a local class that is in a static context different from the static context containing the superclass. For example:
```
class O {
static void foo(int x) {
class C { // in static context, so no enclosing instance
void foo() {
System.out.println(x); /* capture x */
}
}
class I {
static void i(int y) {
class U extends C { // in static context, so no enclosing instance
U(){
super();
System.out.println(y); /* capture y */
}
}
var _ = new U(); // (b)
}
public static void main(String[] args) {
}
}
}
}
```
`javac` 23 compiles this code, but executing the class file for class I results in a verifier error. There is no way to correctly instantiate class U, so the new expression at position (b) is always broken.
With `javac` 24, the class declaration of U results in a compile-time error.
```
class O {
static void foo(int x) {
class C { // in static context, so no enclosing instance
void outer() {
System.out.println(x); // capture x
}
}
class U {
static void test() {
new C(); // (a)
}
}
}
public static void main(String[] args) {
foo(42);
}
}
```
`javac` 23 compiles this program, but executing the classfile for class O throws an internal exception trying to create the instance at position (a).
`javac` 24 requires that any new expression creating an instance of a class C where C is an inner local class that appears in a static context, should appear in the same static context. Thus the new expression at position (a) results in a compile-time error.
There is a similar fix for new expressions that create instances of anonymous classes, that is, new expressions with class bodies.
A similar issue surrounds super constructor invocations in a local class that is in a static context different from the static context containing the superclass. For example:
```
class O {
static void foo(int x) {
class C { // in static context, so no enclosing instance
void foo() {
System.out.println(x); /* capture x */
}
}
class I {
static void i(int y) {
class U extends C { // in static context, so no enclosing instance
U(){
super();
System.out.println(y); /* capture y */
}
}
var _ = new U(); // (b)
}
public static void main(String[] args) {
}
}
}
}
```
`javac` 23 compiles this code, but executing the class file for class I results in a verifier error. There is no way to correctly instantiate class U, so the new expression at position (b) is always broken.
With `javac` 24, the class declaration of U results in a compile-time error.