8317376: Minor improvements to the 'this' escape analyzer

Reviewed-by: vromero
This commit is contained in:
Archie Cobbs 2024-04-17 17:35:17 +00:00 committed by Vicente Romero
parent 4895a15a77
commit 064628471b
20 changed files with 756 additions and 375 deletions

View File

@ -53,7 +53,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JIGSAW_TOOLS, \
build/tools/jigsaw, \ build/tools/jigsaw, \
COPY := .properties .html, \ COPY := .properties .html, \
BIN := $(TOOLS_CLASSES_DIR), \ BIN := $(TOOLS_CLASSES_DIR), \
DISABLED_WARNINGS := fallthrough this-escape, \ DISABLED_WARNINGS := fallthrough, \
JAVAC_FLAGS := \ JAVAC_FLAGS := \
--add-modules jdk.jdeps \ --add-modules jdk.jdeps \
--add-exports java.base/jdk.internal.module=ALL-UNNAMED \ --add-exports java.base/jdk.internal.module=ALL-UNNAMED \

View File

@ -1,26 +0,0 @@
#
# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
DISABLED_WARNINGS_java += this-escape

View File

@ -23,8 +23,6 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
DOCLINT += -Xdoclint:all/protected \ DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:java.*,javax.*' '-Xdoclint/package:java.*,javax.*'
CLEAN_FILES += $(wildcard \ CLEAN_FILES += $(wildcard \

View File

@ -23,6 +23,4 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
COPY += .dat COPY += .dat

View File

@ -66,7 +66,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \
SRC := $(TOPDIR)/make/langtools/src/classes, \ SRC := $(TOPDIR)/make/langtools/src/classes, \
INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \ INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javac, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javac, \
DISABLED_WARNINGS := options this-escape, \ DISABLED_WARNINGS := options, \
JAVAC_FLAGS := \ JAVAC_FLAGS := \
$(COMPILECREATESYMBOLS_ADD_EXPORTS), \ $(COMPILECREATESYMBOLS_ADD_EXPORTS), \
)) ))

View File

@ -1,26 +0,0 @@
#
# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
DISABLED_WARNINGS_java += this-escape

View File

@ -56,7 +56,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \
$(TOPDIR)/src/jdk.jdeps/share/classes, \ $(TOPDIR)/src/jdk.jdeps/share/classes, \
INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \ INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javadoc, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javadoc, \
DISABLED_WARNINGS := options this-escape, \ DISABLED_WARNINGS := options, \
JAVAC_FLAGS := \ JAVAC_FLAGS := \
$(INTERIM_LANGTOOLS_ARGS) \ $(INTERIM_LANGTOOLS_ARGS) \
$(COMPILECREATESYMBOLS_ADD_EXPORTS), \ $(COMPILECREATESYMBOLS_ADD_EXPORTS), \

View File

@ -23,6 +23,4 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
COPY += _options COPY += _options

View File

@ -23,8 +23,6 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
COPY += .gif .png COPY += .gif .png
CLEAN_FILES += $(wildcard \ CLEAN_FILES += $(wildcard \

View File

@ -26,8 +26,6 @@
include GensrcCommon.gmk include GensrcCommon.gmk
include GensrcProperties.gmk include GensrcProperties.gmk
DISABLED_WARNINGS_java += this-escape
$(eval $(call SetupVersionProperties, JAVAP_VERSION, \ $(eval $(call SetupVersionProperties, JAVAP_VERSION, \
com/sun/tools/javap/resources/version.properties)) com/sun/tools/javap/resources/version.properties))

View File

@ -25,8 +25,6 @@
include LauncherCommon.gmk include LauncherCommon.gmk
DISABLED_WARNINGS_java += this-escape
################################################################################ ################################################################################
## Build javap ## Build javap
################################################################################ ################################################################################

View File

@ -23,8 +23,6 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
EXCLUDES += \ EXCLUDES += \
com/sun/tools/example/debug/bdi \ com/sun/tools/example/debug/bdi \
com/sun/tools/example/debug/event \ com/sun/tools/example/debug/event \

View File

@ -23,8 +23,6 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
COPY += .gif .png .txt .spec .script .prerm .preinst \ COPY += .gif .png .txt .spec .script .prerm .preinst \
.postrm .postinst .list .sh .desktop .copyright .control .plist .template \ .postrm .postinst .list .sh .desktop .copyright .control .plist .template \
.icns .scpt .wxs .wxl .wxi .ico .bmp .tiff .service .icns .scpt .wxs .wxl .wxi .ico .bmp .tiff .service

View File

@ -23,8 +23,6 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
COPY += _dict _th COPY += _dict _th
# Exclude BreakIterator classes that are just used in compile process to generate # Exclude BreakIterator classes that are just used in compile process to generate
# data files and shouldn't go in the product # data files and shouldn't go in the product

View File

@ -23,8 +23,6 @@
# questions. # questions.
# #
DISABLED_WARNINGS_java += this-escape
# No SCTP implementation on Mac OS X or AIX. These classes should be excluded. # No SCTP implementation on Mac OS X or AIX. These classes should be excluded.
SCTP_IMPL_CLASSES = \ SCTP_IMPL_CLASSES = \
$(TOPDIR)/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java \ $(TOPDIR)/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java \

View File

@ -231,7 +231,7 @@ public class Flow {
new AssignAnalyzer().analyzeTree(env, make); new AssignAnalyzer().analyzeTree(env, make);
new FlowAnalyzer().analyzeTree(env, make); new FlowAnalyzer().analyzeTree(env, make);
new CaptureAnalyzer().analyzeTree(env, make); new CaptureAnalyzer().analyzeTree(env, make);
new ThisEscapeAnalyzer(names, syms, types, log, lint).analyzeTree(env); new ThisEscapeAnalyzer(names, syms, types, rs, log, lint).analyzeTree(env);
} }
public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) { public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {

View File

@ -182,6 +182,41 @@ public class TreeInfo {
} }
} }
/** Check if the given tree is an explicit reference to the 'this' instance of the
* class currently being compiled. This is true if tree is:
* - An unqualified 'this' identifier
* - A 'super' identifier qualified by a class name whose type is 'currentClass' or a supertype
* - A 'this' identifier qualified by a class name whose type is 'currentClass' or a supertype
* but also NOT an enclosing outer class of 'currentClass'.
*/
public static boolean isExplicitThisReference(Types types, Type.ClassType currentClass, JCTree tree) {
switch (tree.getTag()) {
case PARENS:
return isExplicitThisReference(types, currentClass, skipParens(tree));
case IDENT: {
JCIdent ident = (JCIdent)tree;
Names names = ident.name.table.names;
return ident.name == names._this || ident.name == names._super;
}
case SELECT: {
JCFieldAccess select = (JCFieldAccess)tree;
Type selectedType = types.erasure(select.selected.type);
if (!selectedType.hasTag(TypeTag.CLASS))
return false;
Symbol.ClassSymbol currentClassSym = (Symbol.ClassSymbol)((Type.ClassType)types.erasure(currentClass)).tsym;
Symbol.ClassSymbol selectedClassSym = (Symbol.ClassSymbol)((Type.ClassType)selectedType).tsym;
Names names = select.name.table.names;
return currentClassSym.isSubClass(selectedClassSym, types) &&
(select.name == names._super ||
(select.name == names._this &&
(currentClassSym == selectedClassSym ||
!currentClassSym.isEnclosedBy(selectedClassSym))));
}
default:
return false;
}
}
/** Is this a call to super? /** Is this a call to super?
*/ */
public static boolean isSuperCall(JCTree tree) { public static boolean isSuperCall(JCTree tree) {

View File

@ -313,7 +313,7 @@ public class ThisEscape {
} }
} }
public class Inner2 { public static class Inner2 {
public Inner2() { public Inner2() {
new Test3().mightLeak(); new Test3().mightLeak();
} }
@ -585,6 +585,124 @@ public class ThisEscape {
} }
} }
// Verify 'this' escape correctly follows outer instances through member classes
public static class ThisEscapeOuterRef1 {
class Inner {
void foo() {
ThisEscapeOuterRef1.this.hashCode();
}
}
public ThisEscapeOuterRef1() {
new Inner().foo();
}
}
// Verify 'this' escape correctly follows outer instances through local classes
public static class ThisEscapeOuterRef2 {
public ThisEscapeOuterRef2() {
class Inner {
void foo() {
ThisEscapeOuterRef2.this.hashCode();
}
}
new Inner().foo();
}
}
// Verify 'this' escape correctly follows outer instances through anonymous classes
public static class ThisEscapeOuterRef3 {
public ThisEscapeOuterRef3() {
new Runnable() {
public void run() {
ThisEscapeOuterRef3.this.hashCode(); // leak here
}
}.run();
}
}
// Verify 'this' escape knows that enhanced for loops invoke iterator(), etc.
public static class ThisEscapeForeach1 implements Iterable<Object> {
public ThisEscapeForeach1() {
for (Object v : this)
v.hashCode(); // possible leak here
}
@Override
public final java.util.Iterator<Object> iterator() {
return new java.util.Iterator<Object>() {
@Override
public boolean hasNext() {
return true;
}
@Override
public Object next() {
return ThisEscapeForeach1.this;
}
};
}
}
// Verify 'this' escape tracks deferred return values
public static class DeferredReturn {
public DeferredReturn(int x) {
((Supplier<DeferredReturn>)this::self).get().mightLeak(); // leak here
}
public DeferredReturn(float x) {
((Supplier<DeferredReturn>)() -> this).get().mightLeak(); // leak here
}
private final DeferredReturn self() {
return this;
}
protected void mightLeak() {
}
}
// Verify 'this' escape properly tracks variable types
public static class TypeTracking {
public TypeTracking() {
Runnable r = new Runnable() {
public void run() {
TypeTracking.this.mightLeak();
}
};
r.run(); // leak here - we know "r" has type TypeTracking$1
}
protected void mightLeak() {
}
}
// Verify 'this' escape doesn't warn for outer instances of anonymous classes that don't use them
public static class ThisEscapeOuterRef4 {
public ThisEscapeOuterRef4() {
new Runnable() {
public void run() {
// there is no leak in here
}
}.run();
}
}
// Verify 'this' escape doesn't warn for doubly-outer instance references
public static class ThisEscapeDoubleOuter {
public class Inner1 {
public Inner1() {
new Inner2().foo(); // NOT a 'this' leak
}
class Inner2 {
void foo() {
ThisEscapeDoubleOuter.this.hashCode();
}
}
}
}
// Verify 'this' escape detection doesn't warn for sealed classes with local permits // Verify 'this' escape detection doesn't warn for sealed classes with local permits
public static sealed class ThisEscapeSealed permits ThisEscapeSealed.Sub1, ThisEscapeSealed.Sub2 { public static sealed class ThisEscapeSealed permits ThisEscapeSealed.Sub1, ThisEscapeSealed.Sub2 {

View File

@ -23,4 +23,16 @@ ThisEscape.java:396:17: compiler.warn.possible.this.escape
ThisEscape.java:401:30: compiler.warn.possible.this.escape.location ThisEscape.java:401:30: compiler.warn.possible.this.escape.location
ThisEscape.java:444:28: compiler.warn.possible.this.escape ThisEscape.java:444:28: compiler.warn.possible.this.escape
ThisEscape.java:473:27: compiler.warn.possible.this.escape ThisEscape.java:473:27: compiler.warn.possible.this.escape
25 warnings ThisEscape.java:596:28: compiler.warn.possible.this.escape
ThisEscape.java:592:50: compiler.warn.possible.this.escape.location
ThisEscape.java:608:28: compiler.warn.possible.this.escape
ThisEscape.java:605:54: compiler.warn.possible.this.escape.location
ThisEscape.java:619:18: compiler.warn.possible.this.escape
ThisEscape.java:617:54: compiler.warn.possible.this.escape.location
ThisEscape.java:627:27: compiler.warn.possible.this.escape
ThisEscape.java:648:55: compiler.warn.possible.this.escape
ThisEscape.java:652:55: compiler.warn.possible.this.escape
ThisEscape.java:672:18: compiler.warn.possible.this.escape
ThisEscape.java:669:48: compiler.warn.possible.this.escape.location
ThisEscape.java:726:32: compiler.warn.possible.this.escape
37 warnings