11/*******************************************************************************
2- * Copyright (c) 2017-2019 Microsoft Corporation and others.
2+ * Copyright (c) 2017-2020 Microsoft Corporation and others.
33 * All rights reserved. This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License v1.0
55 * which accompanies this distribution, and is available at
1515import java .util .List ;
1616import java .util .Map ;
1717import java .util .Objects ;
18+ import java .util .function .Consumer ;
1819import java .util .logging .Level ;
1920import java .util .logging .Logger ;
2021import java .util .stream .Collectors ;
@@ -55,12 +56,11 @@ public static boolean hasChildren(Value value, boolean includeStatic) {
5556 if (value == null || !(value instanceof ObjectReference )) {
5657 return false ;
5758 }
58- Type type = value . type ();
59+ ReferenceType type = (( ObjectReference ) value ). referenceType ();
5960 if (type instanceof ArrayType ) {
6061 return ((ArrayReference ) value ).length () > 0 ;
6162 }
62- return value .type () instanceof ReferenceType && ((ReferenceType ) type ).allFields ().stream ()
63- .filter (t -> includeStatic || !t .isStatic ()).toArray ().length > 0 ;
63+ return type .allFields ().stream ().anyMatch (t -> includeStatic || !t .isStatic ());
6464 }
6565
6666 /**
@@ -74,7 +74,7 @@ public static boolean hasChildren(Value value, boolean includeStatic) {
7474 */
7575 public static List <Variable > listFieldVariables (ObjectReference obj , boolean includeStatic ) throws AbsentInformationException {
7676 List <Variable > res = new ArrayList <>();
77- Type type = obj .type ();
77+ ReferenceType type = obj .referenceType ();
7878 if (type instanceof ArrayType ) {
7979 int arrayIndex = 0 ;
8080 boolean isUnboundedArrayType = Objects .equals (type .signature (), "[Ljava/lang/Object;" );
@@ -85,7 +85,7 @@ public static List<Variable> listFieldVariables(ObjectReference obj, boolean inc
8585 }
8686 return res ;
8787 }
88- List <Field > fields = obj . referenceType () .allFields ().stream ().filter (t -> includeStatic || !t .isStatic ())
88+ List <Field > fields = type .allFields ().stream ().filter (t -> includeStatic || !t .isStatic ())
8989 .sorted ((a , b ) -> {
9090 try {
9191 boolean v1isStatic = a .isStatic ();
@@ -102,11 +102,16 @@ public static List<Variable> listFieldVariables(ObjectReference obj, boolean inc
102102 return -1 ;
103103 }
104104 }).collect (Collectors .toList ());
105- fields .forEach (f -> {
106- Variable var = new Variable (f .name (), obj .getValue (f ));
107- var .field = f ;
108- res .add (var );
109- });
105+
106+ bulkFetchValues (fields , DebugSettings .getCurrent ().limitOfVariablesPerJdwpRequest , (currentPage -> {
107+ Map <Field , Value > fieldValues = obj .getValues (currentPage );
108+ for (Field currentField : currentPage ) {
109+ Variable var = new Variable (currentField .name (), fieldValues .get (currentField ));
110+ var .field = currentField ;
111+ res .add (var );
112+ }
113+ }));
114+
110115 return res ;
111116 }
112117
@@ -155,13 +160,18 @@ public static List<Variable> listLocalVariables(StackFrame stackFrame) throws Ab
155160 return res ;
156161 }
157162 try {
158- List <LocalVariable > localVariables = stackFrame .visibleVariables ();
159- Map <LocalVariable , Value > values = stackFrame .getValues (localVariables );
160- for (LocalVariable localVariable : localVariables ) {
161- Variable var = new Variable (localVariable .name (), values .get (localVariable ));
162- var .local = localVariable ;
163- res .add (var );
164- }
163+ List <LocalVariable > visibleVariables = stackFrame .visibleVariables ();
164+ // When using the API StackFrame.getValues() to batch fetch the variable values, the JDI
165+ // probably throws timeout exception if the variables to be passed at one time are large.
166+ // So use paging to fetch the values in chunks.
167+ bulkFetchValues (visibleVariables , DebugSettings .getCurrent ().limitOfVariablesPerJdwpRequest , (currentPage -> {
168+ Map <LocalVariable , Value > values = stackFrame .getValues (currentPage );
169+ for (LocalVariable localVariable : currentPage ) {
170+ Variable var = new Variable (localVariable .name (), values .get (localVariable ));
171+ var .local = localVariable ;
172+ res .add (var );
173+ }
174+ }));
165175 } catch (AbsentInformationException ex ) {
166176 // avoid listing variable on native methods
167177
@@ -228,11 +238,16 @@ public static Variable getThisVariable(StackFrame stackFrame) {
228238 public static List <Variable > listStaticVariables (StackFrame stackFrame ) {
229239 List <Variable > res = new ArrayList <>();
230240 ReferenceType type = stackFrame .location ().declaringType ();
231- type .allFields ().stream ().filter (TypeComponent ::isStatic ).forEach (field -> {
232- Variable staticVar = new Variable (field .name (), type .getValue (field ));
233- staticVar .field = field ;
234- res .add (staticVar );
235- });
241+ List <Field > fields = type .allFields ().stream ().filter (TypeComponent ::isStatic ).collect (Collectors .toList ());
242+ bulkFetchValues (fields , DebugSettings .getCurrent ().limitOfVariablesPerJdwpRequest , (currentPage -> {
243+ Map <Field , Value > fieldValues = type .getValues (currentPage );
244+ for (Field currentField : currentPage ) {
245+ Variable var = new Variable (currentField .name (), fieldValues .get (currentField ));
246+ var .field = currentField ;
247+ res .add (var );
248+ }
249+ }));
250+
236251 return res ;
237252 }
238253
@@ -289,6 +304,18 @@ public static String getEvaluateName(String name, String containerName, boolean
289304 return String .format ("%s.%s" , containerName , name );
290305 }
291306
307+ private static <T > void bulkFetchValues (List <T > elements , int numberPerPage , Consumer <List <T >> consumer ) {
308+ int size = elements .size ();
309+ numberPerPage = numberPerPage < 1 ? 1 : numberPerPage ;
310+ int page = size / numberPerPage + Math .min (size % numberPerPage , 1 );
311+ for (int i = 0 ; i < page ; i ++) {
312+ int pageStart = i * numberPerPage ;
313+ int pageEnd = Math .min (pageStart + numberPerPage , size );
314+ List <T > currentPage = elements .subList (pageStart , pageEnd );
315+ consumer .accept (currentPage );
316+ }
317+ }
318+
292319 private VariableUtils () {
293320
294321 }
0 commit comments