[classloads] remove dead analyser

Summary: As per title

Reviewed By: jvillard

Differential Revision: D22019146

fbshipit-source-id: 3837993e5
master
Nikos Gorogiannis 5 years ago committed by Facebook GitHub Bot
parent 4bbe5a064b
commit 23c1b4f960

2
.gitignore vendored

@ -50,8 +50,6 @@ duplicates.txt
/infer/tests/build_systems/incremental_analysis_cost_change/src
/infer/tests/build_systems/incremental_analysis_add_procedure/src
/infer/tests/build_systems/java_test_determinator/*.test
/infer/tests/codetoanalyze/java/classloads/*.loads
/infer/tests/codetoanalyze/java/classloads/loads.exp
/_release
/infer-source

@ -157,7 +157,6 @@ DIRECT_TESTS += \
java_biabduction \
java_bufferoverrun \
java_checkers \
java_classloads \
java_nullsafe \
java_hoisting \
java_hoistingExpensive \

@ -47,14 +47,6 @@ OPTIONS
reactive analysis should start. Source files should be specified
relative to project root or be absolute
--class-loads
Activates: checker class-loads: Compute set of Java classes
loaded. (Conversely: --no-class-loads)
--class-loads-only
Activates: Enable class-loads and disable all other checkers
(Conversely: --no-class-loads-only)
--continue-analysis
Activates: Continue the analysis after more targets are captured
by --continue. The other analysis options should be given the same

@ -228,14 +228,6 @@ OPTIONS
arrays) is not done element by element but using a builtin
function that each analysis has to model. See also infer-analyze(1) and infer-capture(1).
--class-loads
Activates: checker class-loads: Compute set of Java classes
loaded. (Conversely: --no-class-loads) See also infer-analyze(1).
--class-loads-only
Activates: Enable class-loads and disable all other checkers
(Conversely: --no-class-loads-only) See also infer-analyze(1).
--compilation-database +path
File that contain compilation commands (can be specified multiple
times) See also infer-capture(1).
@ -394,7 +386,6 @@ OPTIONS
CHECKERS_IMMUTABLE_CAST (enabled by default),
CHECKERS_PRINTF_ARGS (enabled by default),
CLASS_CAST_EXCEPTION (disabled by default),
CLASS_LOAD (enabled by default),
COMPONENT_FACTORY_FUNCTION (enabled by default),
COMPONENT_FILE_CYCLOMATIC_COMPLEXITY (enabled by default),
COMPONENT_FILE_LINE_COUNT (disabled by default),
@ -1330,12 +1321,6 @@ INTERNAL OPTIONS
--clang-libcxx-include-to-override-regex-reset
Cancel the effect of --clang-libcxx-include-to-override-regex.
--class-loads-roots +string
Report class loads of this list of Java methods
--class-loads-roots-reset
Set --class-loads-roots to the empty list.
--classpath string
Specify the Java classpath

@ -116,7 +116,6 @@ OPTIONS
CHECKERS_IMMUTABLE_CAST (enabled by default),
CHECKERS_PRINTF_ARGS (enabled by default),
CLASS_CAST_EXCEPTION (disabled by default),
CLASS_LOAD (enabled by default),
COMPONENT_FACTORY_FUNCTION (enabled by default),
COMPONENT_FILE_CYCLOMATIC_COMPLEXITY (enabled by default),
COMPONENT_FILE_LINE_COUNT (disabled by default),

@ -228,14 +228,6 @@ OPTIONS
arrays) is not done element by element but using a builtin
function that each analysis has to model. See also infer-analyze(1) and infer-capture(1).
--class-loads
Activates: checker class-loads: Compute set of Java classes
loaded. (Conversely: --no-class-loads) See also infer-analyze(1).
--class-loads-only
Activates: Enable class-loads and disable all other checkers
(Conversely: --no-class-loads-only) See also infer-analyze(1).
--compilation-database +path
File that contain compilation commands (can be specified multiple
times) See also infer-capture(1).
@ -394,7 +386,6 @@ OPTIONS
CHECKERS_IMMUTABLE_CAST (enabled by default),
CHECKERS_PRINTF_ARGS (enabled by default),
CLASS_CAST_EXCEPTION (disabled by default),
CLASS_LOAD (enabled by default),
COMPONENT_FACTORY_FUNCTION (enabled by default),
COMPONENT_FILE_CYCLOMATIC_COMPLEXITY (enabled by default),
COMPONENT_FILE_LINE_COUNT (disabled by default),

@ -13,7 +13,6 @@ type t =
; biabduction: BiabductionSummary.t option
; buffer_overrun_analysis: BufferOverrunAnalysisSummary.t option
; buffer_overrun_checker: BufferOverrunCheckerSummary.t option
; class_loads: ClassLoadsDomain.summary option
; cost: CostDomain.summary option
; lab_resource_leaks: ResourceLeakDomain.summary option
; litho_required_props: LithoDomain.summary option
@ -39,7 +38,6 @@ let fields =
~biabduction:(fun f -> mk_pe f "Biabduction" BiabductionSummary.pp)
~buffer_overrun_analysis:(fun f -> mk f "BufferOverrunAnalysis" BufferOverrunAnalysisSummary.pp)
~buffer_overrun_checker:(fun f -> mk f "BufferOverrunChecker" BufferOverrunCheckerSummary.pp)
~class_loads:(fun f -> mk f "ClassLoads" ClassLoadsDomain.pp_summary)
~cost:(fun f -> mk f "Cost" CostDomain.pp_summary)
~litho_required_props:(fun f -> mk f "Litho Required Props" LithoDomain.pp_summary)
~pulse:(fun f -> mk f "Pulse" PulseSummary.pp)
@ -63,7 +61,6 @@ let empty =
; biabduction= None
; buffer_overrun_analysis= None
; buffer_overrun_checker= None
; class_loads= None
; cost= None
; lab_resource_leaks= None
; litho_required_props= None

@ -17,7 +17,6 @@ include sig
; biabduction: BiabductionSummary.t option
; buffer_overrun_analysis: BufferOverrunAnalysisSummary.t option
; buffer_overrun_checker: BufferOverrunCheckerSummary.t option
; class_loads: ClassLoadsDomain.summary option
; cost: CostDomain.summary option
; lab_resource_leaks: ResourceLeakDomain.summary option
; litho_required_props: LithoDomain.summary option

@ -77,9 +77,6 @@ let all_checkers =
(* The order of the list is important for those checkers that depend on other checkers having run
before them. *)
[ {checker= SelfInBlock; callbacks= [(intraprocedural SelfInBlock.checker, Clang)]}
; { checker= ClassLoads
; callbacks= [(interprocedural Payloads.Fields.class_loads ClassLoads.analyze_procedure, Java)]
}
; { checker= Purity
; callbacks=
(let purity =

@ -13,7 +13,6 @@ type t =
| Biabduction
| BufferOverrunAnalysis
| BufferOverrunChecker
| ClassLoads
| Cost
| Eradicate
| FragmentRetainsView
@ -120,18 +119,6 @@ let config_unsafe checker =
; cli_flags= Some {deprecated= []; show_in_help= true}
; enabled_by_default= false
; activates= [BufferOverrunAnalysis] }
| ClassLoads ->
{ id= "class-loads"
; kind=
UserFacingDeprecated
{ title= "Class loading analysis"
; markdown_body= ""
; deprecation_message= "Unmaintained prototype." }
; support= supports_java
; short_documentation= "Compute set of Java classes loaded."
; cli_flags= Some {deprecated= []; show_in_help= true}
; enabled_by_default= false
; activates= [] }
| Cost ->
{ id= "cost"
; kind= UserFacing {title= "Cost: Runtime Complexity Analysis"; markdown_body= ""}

@ -12,7 +12,6 @@ type t =
| Biabduction
| BufferOverrunAnalysis
| BufferOverrunChecker
| ClassLoads
| Cost
| Eradicate
| FragmentRetainsView

@ -889,10 +889,6 @@ and clang_libcxx_include_to_override_regex =
$(b,-I /path/to/infer/facebook-clang-plugins/clang/install/include/c++/v1)."
and class_loads_roots =
CLOpt.mk_string_list ~long:"class-loads-roots" "Report class loads of this list of Java methods"
and classpath = CLOpt.mk_string_opt ~long:"classpath" "Specify the Java classpath"
and compilation_database =
@ -2708,8 +2704,6 @@ and clang_libcxx_include_to_override_regex = !clang_libcxx_include_to_override_r
and classpath = !classpath
and class_loads_roots = String.Set.of_list !class_loads_roots
and compute_analytics = !compute_analytics
and continue_analysis = !continue_analysis

@ -226,8 +226,6 @@ val clang_idirafter_to_override_regex : Str.regexp option
val clang_libcxx_include_to_override_regex : string option
val class_loads_roots : String.Set.t
val command : InferCommand.t
val compute_analytics : bool

@ -331,8 +331,6 @@ let class_cast_exception =
Biabduction
let class_load = register_from_string ~id:"CLASS_LOAD" Warning ClassLoads
let component_factory_function =
register_from_string ~id:"COMPONENT_FACTORY_FUNCTION" Advice Linters
~user_documentation:[%blob "../../documentation/issues/COMPONENT_FACTORY_FUNCTION.md"]

@ -139,8 +139,6 @@ val checkers_printf_args : t
val class_cast_exception : t
val class_load : t
val complexity_increase : kind:CostKind.t -> is_on_ui_thread:bool -> t
val component_factory_function : t

@ -1,138 +0,0 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module L = Logging
(* Sources: Java Virtual Machine Specification
- Chapter 5. Loading, Linking and Initializing
- Chapter 6. The Java Virtual Machine Instruction Set
*)
(* TODO
- catch / throw with exception classes
*)
let do_call {InterproceduralAnalysis.analyze_dependency} callee loc init =
analyze_dependency callee
|> Option.fold ~init ~f:(fun acc (_, summary) ->
ClassLoadsDomain.integrate_summary callee loc acc summary )
(** fully load a class given the typename *)
let rec load_class ({InterproceduralAnalysis.tenv} as analysis_data) loc astate class_name =
(* don't bother if class is already loaded *)
if ClassLoadsDomain.mem_typename class_name astate then astate
else
(* load the class itself *)
let astate1 = ClassLoadsDomain.add_typename loc astate class_name in
(* load classes referenced by the class initializer *)
let astate2 =
let class_initializer = Procname.(Java (Java.get_class_initializer class_name)) in
(* NB may recurse if we are in class init but the shortcircuiting above makes it a no-op *)
do_call analysis_data class_initializer loc astate1
in
(* finally, recursively load all superclasses *)
Tenv.lookup tenv class_name
|> Option.value_map ~default:[] ~f:(fun tstruct -> tstruct.Struct.supers)
|> List.fold ~init:astate2 ~f:(load_class analysis_data loc)
let load_type analysis_data loc (typ : Typ.t) astate =
match typ with
| {desc= Tstruct name} | {desc= Tptr ({desc= Tstruct name}, _)} ->
load_class analysis_data loc astate name
| _ ->
astate
let rec load_array analysis_data loc (typ : Typ.t) astate =
match typ with
| {desc= Tarray {elt}} ->
load_array analysis_data loc elt astate
| _ ->
load_type analysis_data loc typ astate
let rec add_loads_of_exp analysis_data loc (exp : Exp.t) astate =
match exp with
| Const (Cclass class_ident) ->
(* [X.class] expressions *)
let class_str = Ident.name_to_string class_ident |> JavaClassName.from_string in
let class_name = Typ.JavaClass class_str in
load_class analysis_data loc astate class_name
| Sizeof {typ= {desc= Tarray {elt}}} ->
(* anewarray / multinewarray *)
load_array analysis_data loc elt astate
| Cast (_, e) | UnOp (_, e, _) | Exn e ->
(* NB Cast is only used for primitive types *)
add_loads_of_exp analysis_data loc e astate
| BinOp (_, e1, e2) ->
add_loads_of_exp analysis_data loc e1 astate |> add_loads_of_exp analysis_data loc e2
| Lfield (e, _, typ') ->
(* getfield / getstatic / putfield / putstatic *)
load_type analysis_data loc typ' astate |> add_loads_of_exp analysis_data loc e
| Var _ | Const _ | Closure _ | Sizeof _ | Lindex _ | Lvar _ ->
astate
let exec_call analysis_data callee args loc astate =
match args with
| [_; (Exp.Sizeof {typ}, _)] when Procname.equal callee BuiltinDecl.__instanceof ->
(* this matches downcasts/instanceof and exception handlers *)
load_type analysis_data loc typ astate
| _ ->
(* invokeinterface / invokespecial / invokestatic / invokevirtual / new *)
List.fold args ~init:astate ~f:(fun acc (exp, _) ->
add_loads_of_exp analysis_data loc exp acc )
|> do_call analysis_data callee loc
let exec_instr analysis_data astate _ (instr : Sil.instr) =
match instr with
| Call (_, Const (Cfun callee), args, loc, _) ->
exec_call analysis_data callee args loc astate
| Load {e= exp; loc} | Prune (exp, loc, _, _) ->
(* NB the java frontend seems to always translate complex guards into a sequence of
instructions plus a prune on logical vars only. So the below is only for completeness. *)
add_loads_of_exp analysis_data loc exp astate
| Store {e1; e2; loc} ->
add_loads_of_exp analysis_data loc e1 astate |> add_loads_of_exp analysis_data loc e2
| _ ->
astate
let report_loads {InterproceduralAnalysis.proc_desc; err_log} astate =
let report_load ({ClassLoadsDomain.Event.loc; elem} as event) =
if String.is_prefix ~prefix:"java." elem then ()
else
let ltr = ClassLoadsDomain.Event.make_loc_trace event in
let msg = Format.asprintf "Class %s loaded" elem in
Reporting.log_issue proc_desc err_log ~loc ~ltr ClassLoads IssueType.class_load msg
in
let pname = Procdesc.get_proc_name proc_desc in
Procname.get_class_name pname
|> Option.iter ~f:(fun clazz ->
let method_strname = Procname.get_method pname in
let fullname = clazz ^ "." ^ method_strname in
if String.Set.mem Config.class_loads_roots fullname then
ClassLoadsDomain.iter report_load astate )
let analyze_procedure ({InterproceduralAnalysis.proc_desc} as analysis_data) =
let proc_name = Procdesc.get_proc_name proc_desc in
L.debug Analysis Verbose "CL: ANALYZING %a@." Procname.pp proc_name ;
let loc = Procdesc.get_loc proc_desc in
(* load the method's class *)
let init =
Procname.get_class_type_name proc_name
|> Option.fold ~init:ClassLoadsDomain.bottom ~f:(load_class analysis_data loc)
in
let post = Procdesc.fold_instrs proc_desc ~init ~f:(exec_instr analysis_data) in
report_loads analysis_data post ;
L.debug Analysis Verbose "CL: FINISHED ANALYZING %a@." Procname.pp proc_name ;
Some post

@ -1,11 +0,0 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
val analyze_procedure :
ClassLoadsDomain.summary InterproceduralAnalysis.t -> ClassLoadsDomain.summary option

@ -1,56 +0,0 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
module L = Logging
module ClassLoad = struct
include String
let describe = pp
end
module Event =
ExplicitTrace.MakeTraceElemModuloLocation (ClassLoad) (ExplicitTrace.DefaultCallPrinter)
include Event.FiniteSet
let add ({Event.trace} as x) astate =
match find_opt x astate with
| None ->
add x astate
| Some ({Event.trace= trace'} as x') ->
if Int.( <= ) (List.length trace') (List.length trace) then astate
else remove x' astate |> add x
let union xs ys = fold add xs ys
let add_string loc astate clazz =
L.debug Analysis Verbose "CL: LOADING class %s@." clazz ;
let new_event = Event.make clazz loc in
add new_event astate
let mem_typename name astate =
let str_name = Typ.Name.name name in
(* comparison of elements is only over the string component so fake the rest *)
let fake_event = Event.make str_name Location.dummy in
mem fake_event astate
let add_typename loc astate name = Typ.Name.name name |> add_string loc astate
let integrate_summary callee_pname loc astate callee_summary =
L.debug Analysis Verbose "CL: ADDING SUMMARY OF %a@." Procname.pp callee_pname ;
let callsite = CallSite.make callee_pname loc in
let summary = with_callsite callee_summary callsite in
union astate summary
type summary = t
let pp_summary = pp

@ -1,26 +0,0 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
module ClassLoad : ExplicitTrace.Element with type t = string
module Event : ExplicitTrace.TraceElem with type elem_t = ClassLoad.t
include AbstractDomain.WithBottom
type summary = t
val pp_summary : F.formatter -> summary -> unit
val mem_typename : Typ.Name.t -> t -> bool
val add_typename : Location.t -> t -> Typ.Name.t -> t
val integrate_summary : Procname.t -> Location.t -> t -> summary -> t
val iter : (Event.t -> unit) -> t -> unit

@ -1,40 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Arrays {
static ArraysB[] arrayB = new ArraysB[10];
static ArraysC[] arrayC = ArraysD.arrayC;
public static void main(String args[]) {
ArraysA[] arrayA = new ArraysA[10];
System.out.println(ArraysF.foo()[0]);
ArraysG[][] arrayG = new ArraysG[10][10];
}
}
class ArraysA {}
class ArraysB {}
class ArraysC {}
class ArraysD {
static ArraysC[] arrayC = new ArraysC[10];
}
class ArraysE {}
class ArraysF {
static ArraysE[] foo() {
return new ArraysE[10];
}
}
class ArraysG {}

@ -1,14 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Basic {
public static void main(String args[]) {
new BasicObj();
}
}
class BasicObj {}

@ -1,32 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Casts {
// there is no way to test this dynamically, as to avoid an exception
// we must first create a CastsC object. So this is more for documenting.
public static void main(String args[]) {
CastsA.downcast(new CastsC());
}
}
class CastsA {
static CastsC downcast(CastsB c) {
return (CastsC) c;
}
static boolean checkclass(CastsD d) {
return d instanceof CastsE;
}
}
class CastsB {}
class CastsC extends CastsB {}
class CastsD {}
class CastsE extends CastsD {}

@ -1,21 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Catch {
public static void main(String args[]) {
try {
foo();
} catch (CatchA a) {
}
}
static void foo() throws CatchA {}
}
class CatchA extends Exception {
static final long serialVersionUID = 0L;
}

@ -1,19 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Const {
public static void main(String args[]) {
synchronized (ConstA.class) {
}
java.lang.Class<ConstB> b = ConstB.class;
}
}
class ConstA {}
class ConstB {}

@ -1,41 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Fields {
FieldsA a;
Fields() {
a = new FieldsA();
}
void foo() {
System.out.println(a.b.c);
}
public static void main(String args[]) {
Fields f = new Fields();
f.foo();
}
}
class FieldsA {
FieldsA() {
b = new FieldsB();
}
FieldsB b;
}
class FieldsB {
FieldsB() {
c = null;
}
FieldsCNoLoad c;
}
class FieldsCNoLoad {}

@ -1,70 +0,0 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# Convention: each Java file must have a single [main] method in the eponymous public class
# This is the root for class loads analysis, and the one executed in the JVM to log loads.
# There is no .exp file committed, the loads are generated by JVM during testing.
TESTS_DIR = ../../..
INFERPRINT_OPTIONS = --issues-tests
SOURCES = $(wildcard *.java)
LOADS = $(patsubst %.java,%.loads,$(SOURCES))
OBJECTS = $(patsubst %.java,%.class,$(SOURCES))
CLASS_LOADS_OPT = $(patsubst %.java,--class-loads-roots %.main,$(SOURCES))
INFER_OPTIONS = --class-loads-only $(CLASS_LOADS_OPT) --debug-exceptions
CLEAN_EXTRA = *.class *.loads loads.exp loads.exp.test
include $(TESTS_DIR)/java.make
INFER_OUT ?= infer-out$(TEST_SUFFIX)
include $(TESTS_DIR)/base.make
.PHONY: clean
clean:
$(REMOVE_DIR) codetoanalyze com issues.exp.test$(TEST_SUFFIX) $(CLEAN_EXTRA)
ifneq ($(INFER_OUT),.)
$(REMOVE_DIR) $(INFER_OUT)
endif
PROJECT_ROOT ?= $(TESTS_DIR)
issues.exp.test$(TEST_SUFFIX): $(INFER_OUT)/report.json $(INFER_BIN)
$(QUIET)$(INFER_BIN) report -q --results-dir $(<D) \
$(INFERPRINT_OPTIONS) $@
infer-out/report.json: $(JAVA_DEPS) $(SOURCES) $(MAKEFILE_LIST)
$(QUIET)$(call silent_on_success,Testing infer/java in $(TEST_REL_DIR),\
$(INFER_BIN) --project-root $(PROJECT_ROOT) \
$(INFER_OPTIONS) -- \
$(JAVAC) -cp $(CLASSPATH) $(SOURCES))
%.loads: %.class
ifeq ($(JDK11_ENABLED),yes)
$(QUIET)java -verbose:class $* | grep "\[info\]\[class,load\]" | cut -f2 -d' ' | grep -vE "^(java|sun|jdk|opened:)" > $@
else
$(QUIET)java -verbose:class $* | grep "^\[Loaded" | cut -f2 -d' ' | grep -vE "^(java|sun)" > $@
endif
# infer compiles as well as analyses; dependency ensures class files are generated
$(OBJECTS): issues.exp.test$(TEST_SUFFIX)
loads.exp: $(LOADS)
$(QUIET)for F in $(LOADS) ; do sed -e "s#^#$(TEST_REL_DIR)/$${F%.*}.java, #" $$F ; done | sort > loads.exp
loads.exp.test: issues.exp.test$(TEST_SUFFIX)
$(QUIET)cat $< | sed 's/^\([^,]*\),.*[,\[]\([^,]*\)\]$$/\1, \2/' | sort > $@
.PHONY: test
test: loads.exp loads.exp.test
$(QUIET)cd $(TESTS_DIR) && \
$(call check_no_diff,$(TEST_REL_DIR)/loads.exp,$(TEST_REL_DIR)/loads.exp.test)
.PHONY: replace
replace:
@:

@ -1,22 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Prune {
public static void main(String args[]) {
if (PruneA.f == 0) {
System.out.println(PruneB.g < 0);
}
}
}
class PruneA {
static int f;
}
class PruneB {
static int g;
}

@ -1,32 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Static {
// this loads StaticA
static StaticA s = new StaticA();
public static void main(String args[]) {
// this loads StaticD
System.out.println(StaticD.static_data);
}
}
class StaticA {
// this loads StaticB
static StaticB b = new StaticB();
}
class StaticB {
// no load here
static StaticCNoLoad c = null;
}
class StaticCNoLoad {}
class StaticD {
static int static_data = 5;
}

@ -1,28 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Super {
public static void main(String args[]) {
// this loads SuperB and SuperA
System.out.println(SuperB.static_data);
// this loads SuperC and SuperD
SuperD.foo();
}
}
class SuperA {}
class SuperB extends SuperA {
static int static_data = 5;
}
class SuperC {}
class SuperD extends SuperC {
public static void foo() {}
}

@ -1,18 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Unique {
public static void main(String args[]) {
// two loads for the same class with distinct locations and traces should be merged into one
UniqueObj u = new UniqueObj();
u.foo();
}
}
class UniqueObj {
void foo() {}
}
Loading…
Cancel
Save