8317376: Minor improvements to the 'this' escape analyzer
Reviewed-by: vromero
This commit is contained in:
parent
4895a15a77
commit
064628471b
@ -53,7 +53,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JIGSAW_TOOLS, \
|
||||
build/tools/jigsaw, \
|
||||
COPY := .properties .html, \
|
||||
BIN := $(TOOLS_CLASSES_DIR), \
|
||||
DISABLED_WARNINGS := fallthrough this-escape, \
|
||||
DISABLED_WARNINGS := fallthrough, \
|
||||
JAVAC_FLAGS := \
|
||||
--add-modules jdk.jdeps \
|
||||
--add-exports java.base/jdk.internal.module=ALL-UNNAMED \
|
||||
|
@ -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
|
@ -23,8 +23,6 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
DOCLINT += -Xdoclint:all/protected \
|
||||
'-Xdoclint/package:java.*,javax.*'
|
||||
CLEAN_FILES += $(wildcard \
|
||||
|
@ -23,6 +23,4 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
COPY += .dat
|
||||
|
@ -66,7 +66,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \
|
||||
SRC := $(TOPDIR)/make/langtools/src/classes, \
|
||||
INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javac, \
|
||||
DISABLED_WARNINGS := options this-escape, \
|
||||
DISABLED_WARNINGS := options, \
|
||||
JAVAC_FLAGS := \
|
||||
$(COMPILECREATESYMBOLS_ADD_EXPORTS), \
|
||||
))
|
||||
|
@ -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
|
@ -56,7 +56,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \
|
||||
$(TOPDIR)/src/jdk.jdeps/share/classes, \
|
||||
INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javadoc, \
|
||||
DISABLED_WARNINGS := options this-escape, \
|
||||
DISABLED_WARNINGS := options, \
|
||||
JAVAC_FLAGS := \
|
||||
$(INTERIM_LANGTOOLS_ARGS) \
|
||||
$(COMPILECREATESYMBOLS_ADD_EXPORTS), \
|
||||
|
@ -23,6 +23,4 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
COPY += _options
|
||||
|
@ -23,8 +23,6 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
COPY += .gif .png
|
||||
|
||||
CLEAN_FILES += $(wildcard \
|
||||
|
@ -26,8 +26,6 @@
|
||||
include GensrcCommon.gmk
|
||||
include GensrcProperties.gmk
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
$(eval $(call SetupVersionProperties, JAVAP_VERSION, \
|
||||
com/sun/tools/javap/resources/version.properties))
|
||||
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
include LauncherCommon.gmk
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
################################################################################
|
||||
## Build javap
|
||||
################################################################################
|
||||
|
@ -23,8 +23,6 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
EXCLUDES += \
|
||||
com/sun/tools/example/debug/bdi \
|
||||
com/sun/tools/example/debug/event \
|
||||
|
@ -23,8 +23,6 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
COPY += .gif .png .txt .spec .script .prerm .preinst \
|
||||
.postrm .postinst .list .sh .desktop .copyright .control .plist .template \
|
||||
.icns .scpt .wxs .wxl .wxi .ico .bmp .tiff .service
|
||||
|
@ -23,8 +23,6 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
COPY += _dict _th
|
||||
# Exclude BreakIterator classes that are just used in compile process to generate
|
||||
# data files and shouldn't go in the product
|
||||
|
@ -23,8 +23,6 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
DISABLED_WARNINGS_java += this-escape
|
||||
|
||||
# No SCTP implementation on Mac OS X or AIX. These classes should be excluded.
|
||||
SCTP_IMPL_CLASSES = \
|
||||
$(TOPDIR)/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java \
|
||||
|
@ -231,7 +231,7 @@ public class Flow {
|
||||
new AssignAnalyzer().analyzeTree(env, make);
|
||||
new FlowAnalyzer().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) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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?
|
||||
*/
|
||||
public static boolean isSuperCall(JCTree tree) {
|
||||
|
@ -313,7 +313,7 @@ public class ThisEscape {
|
||||
}
|
||||
}
|
||||
|
||||
public class Inner2 {
|
||||
public static class Inner2 {
|
||||
public Inner2() {
|
||||
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
|
||||
public static sealed class ThisEscapeSealed permits ThisEscapeSealed.Sub1, ThisEscapeSealed.Sub2 {
|
||||
|
||||
|
@ -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:444:28: 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
|
||||
|
Loading…
Reference in New Issue
Block a user