You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by en...@apache.org on 2022/05/17 13:35:09 UTC

[netbeans] branch master updated (0011e80e81 -> ac86e59bd7)

This is an automated email from the ASF dual-hosted git repository.

entl pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


    from 0011e80e81 Merge pull request #4117 from apache/delivery
     new d299087e12 Quote arguments.
     new ac86e59bd7 Adapt Native Image debugging for CE images.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../modules/cpplite/debugger/CPPFrame.java         |   4 +-
 .../modules/cpplite/debugger/CPPLiteDebugger.java  |   8 +-
 .../modules/cpplite/debugger/CPPVariable.java      |   2 +-
 .../nativeimage/debugger/displayer/DynamicHub.java | 126 +++++
 .../debugger/displayer/JavaFrameDisplayer.java     |  31 +-
 .../debugger/displayer/JavaVariablesDisplayer.java | 522 +++++++++++++++++----
 .../java/nativeimage/debugger/displayer/Utils.java | 146 ++++++
 7 files changed, 728 insertions(+), 111 deletions(-)
 create mode 100644 java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/DynamicHub.java
 create mode 100644 java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/Utils.java


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[netbeans] 01/02: Quote arguments.

Posted by en...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

entl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git

commit d299087e12d12c975145a12d23b372e239f7d9a9
Author: Martin Entlicher <ma...@oracle.com>
AuthorDate: Mon May 16 13:19:29 2022 +0200

    Quote arguments.
---
 .../src/org/netbeans/modules/cpplite/debugger/CPPFrame.java       | 4 ++--
 .../org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java    | 8 ++++----
 .../src/org/netbeans/modules/cpplite/debugger/CPPVariable.java    | 2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPFrame.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPFrame.java
index c7315f5fdc..2c36d6d5d5 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPFrame.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPFrame.java
@@ -158,7 +158,7 @@ public final class CPPFrame implements DVFrame {
                 record = frame.thread.getDebugger().sendAndGet("-stack-list-variables --thread " + frame.thread.getId() + " --frame " + frame.level + " --no-frame-filters 2");
             } else {
                 // from to
-                record = frame.thread.getDebugger().sendAndGet("-var-list-children --thread " + frame.thread.getId() + " --frame " + frame.level + " --all-values " + parentVar.getUniqueName());
+                record = frame.thread.getDebugger().sendAndGet("-var-list-children --thread " + frame.thread.getId() + " --frame " + frame.level + " --all-values " + "\"" + parentVar.getUniqueName() + "\"");
             }
         } catch (InterruptedException ex) {
             return Collections.emptyMap();
@@ -257,7 +257,7 @@ public final class CPPFrame implements DVFrame {
             result.complete(value);
             return result;
         }
-        thread.getDebugger().send(new Command("-var-create --thread " + thread.getId() + " --frame " + level + " - * " + expression) {
+        thread.getDebugger().send(new Command("-var-create --thread " + thread.getId() + " --frame " + level + " - * \"" + expression + "\"") {
             @Override
             protected void onDone(MIRecord record) {
                 MITList results = record.results();
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
index bda4bce1a3..bb41a6fec1 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
@@ -398,12 +398,12 @@ public final class CPPLiteDebugger {
         MIRecord memory;
         String offsetArg;
         if (offset != 0) {
-            offsetArg = "-o " + offset + " ";
+            offsetArg = "-o " + offset + " \"";
         } else {
-            offsetArg = "";
+            offsetArg = "\"";
         }
         try {
-            memory = sendAndGet("-data-read-memory-bytes " + offsetArg + address + " " + length);
+            memory = sendAndGet("-data-read-memory-bytes " + offsetArg + address + "\" " + length);
         } catch (InterruptedException ex) {
             return null;
         }
@@ -434,7 +434,7 @@ public final class CPPLiteDebugger {
     public List<Location> listLocations(String filePath) {
         MIRecord lines;
         try {
-            lines = sendAndGet("-symbol-list-lines " + filePath);
+            lines = sendAndGet("-symbol-list-lines \"" + filePath + "\"");
         } catch (InterruptedException ex) {
             return null;
         }
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPVariable.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPVariable.java
index ec1ef374a7..2b6683d230 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPVariable.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPVariable.java
@@ -121,7 +121,7 @@ public final class CPPVariable implements NIVariable {
     public String getExpressionPath() {
         MIRecord pathRecord;
         try {
-            pathRecord = frame.getThread().getDebugger().sendAndGet("-var-info-path-expression " + uniqueName);
+            pathRecord = frame.getThread().getDebugger().sendAndGet("-var-info-path-expression \"" + uniqueName + "\"");
         } catch (InterruptedException ex) {
             return null;
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists


[netbeans] 02/02: Adapt Native Image debugging for CE images.

Posted by en...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

entl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git

commit ac86e59bd7d72027e8138150c148b1f5bd3510cb
Author: Martin Entlicher <ma...@oracle.com>
AuthorDate: Mon May 16 13:20:16 2022 +0200

    Adapt Native Image debugging for CE images.
---
 .../nativeimage/debugger/displayer/DynamicHub.java | 126 +++++
 .../debugger/displayer/JavaFrameDisplayer.java     |  31 +-
 .../debugger/displayer/JavaVariablesDisplayer.java | 522 +++++++++++++++++----
 .../java/nativeimage/debugger/displayer/Utils.java | 146 ++++++
 4 files changed, 721 insertions(+), 104 deletions(-)

diff --git a/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/DynamicHub.java b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/DynamicHub.java
new file mode 100644
index 0000000000..542a4469ed
--- /dev/null
+++ b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/DynamicHub.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.java.nativeimage.debugger.displayer;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.modules.nativeimage.api.debug.NIVariable;
+
+import static org.netbeans.modules.java.nativeimage.debugger.displayer.JavaVariablesDisplayer.PRIVATE;
+import static org.netbeans.modules.java.nativeimage.debugger.displayer.JavaVariablesDisplayer.PUBLIC;
+import static org.netbeans.modules.java.nativeimage.debugger.displayer.Utils.findChild;
+import static org.netbeans.modules.java.nativeimage.debugger.displayer.Utils.getVarsByName;
+
+/**
+ * Hub of the native image object.
+ */
+final class DynamicHub {
+
+    private static final String HUB = "hub";                 // NOI18N
+    private static final String HUB_TYPE = "hubType";        // NOI18N
+    private static final int HUB_TYPE_INSTANCE = 2; // Instances are less than or equal to 2
+    private static final int HUB_TYPE_ARRAY = 4; // Arrays are greater than or equal to 4
+    private static final String OBJ_HEADER = "_objhdr";      // NOI18N
+    private static final String NAME = "name";               // NOI18N
+
+    private final NIVariable hub;
+    private final Map<String, NIVariable> childrenByName;
+
+    enum HubType {
+
+        OBJECT,
+        ARRAY;
+
+        static HubType getFrom(int hubType) {
+            if (hubType <= HUB_TYPE_INSTANCE) {
+                return OBJECT;
+            }
+            if (hubType >= HUB_TYPE_ARRAY) {
+                return ARRAY;
+            }
+            return null;
+        }
+    }
+
+    private DynamicHub(NIVariable hub) {
+        this.hub = hub;
+        this.childrenByName = getVarsByName(hub.getChildren());
+    }
+
+    @CheckForNull
+    static DynamicHub find(NIVariable var) {
+        NIVariable object = findObjectType(var);
+        if (object == null) {
+            return null;
+        }
+        NIVariable[] children = object.getChildren();
+        NIVariable hub = findChild(children, OBJ_HEADER, PUBLIC, HUB, Class.class.getName(), PRIVATE);
+        if (hub != null) {
+            return new DynamicHub(hub);
+        } else {
+            return null;
+        }
+    }
+
+    @CheckForNull
+    private static NIVariable findObjectType(NIVariable var) {
+        NIVariable[] children = var.getChildren();
+        if (children.length < 1) {
+            return null;
+        }
+        if (children[0].getName().equals(Object.class.getName())) {
+            return children[0];
+        }
+        // Prevent from infinite recursion
+        Set<String> visitedNames = new HashSet<>();
+        var = children[0];
+        do {
+            children = var.getChildren();
+            if (children.length < 1) {
+                return null;
+            }
+            var = children[0];
+            if (var.getName().equals(Object.class.getName())) {
+                return var;
+            }
+        } while (visitedNames.add(var.getName()));
+        return null;
+    }
+
+    @CheckForNull
+    HubType getType() {
+        NIVariable hubTypeVar = childrenByName.get(HUB_TYPE);
+        if (hubTypeVar == null) {
+            return null;
+        }
+        try {
+            int hubType = Integer.parseInt(hubTypeVar.getValue());
+            return HubType.getFrom(hubType);
+        } catch (NumberFormatException ex) {
+            return null;
+        }
+    }
+
+    @CheckForNull
+    NIVariable findClassNameVar() {
+        return childrenByName.get(NAME);
+    }
+}
diff --git a/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaFrameDisplayer.java b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaFrameDisplayer.java
index 6c40c8b724..9cd025427a 100644
--- a/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaFrameDisplayer.java
+++ b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaFrameDisplayer.java
@@ -77,17 +77,30 @@ public final class JavaFrameDisplayer implements FrameDisplayer {
         if (methodEnd < 0) {
             methodEnd = functionName.length();
         }
-        int methodStart = functionName.lastIndexOf('.', methodEnd);
-        if (methodStart < 0) {
-            clsMethod = functionName.substring(0, methodEnd);
-        } else {
-            int clsStart = functionName.lastIndexOf('.', methodStart - 1);
+        int methodStart = functionName.indexOf("::");
+        if (methodStart > 0) {
+            int clsStart = functionName.lastIndexOf('.', methodStart);
             if (clsStart < 0) {
                 clsStart = 0;
             } else {
                 clsStart++;
             }
-            clsMethod = functionName.substring(clsStart, methodEnd);
+            String clazz = functionName.substring(clsStart, methodStart);
+            String method = functionName.substring(methodStart + 2, methodEnd);
+            clsMethod = clazz + '.' + method;
+        } else {
+            methodStart = functionName.lastIndexOf('.', methodEnd);
+            if (methodStart < 0) {
+                clsMethod = functionName.substring(0, methodEnd);
+            } else {
+                int clsStart = functionName.lastIndexOf('.', methodStart - 1);
+                if (clsStart < 0) {
+                    clsStart = 0;
+                } else {
+                    clsStart++;
+                }
+                clsMethod = functionName.substring(clsStart, methodEnd);
+            }
         }
         int line = frame.getLine();
         if (line < 0) {
@@ -104,6 +117,7 @@ public final class JavaFrameDisplayer implements FrameDisplayer {
             methodEnd = functionName.length();
         }
         String clsMethod = functionName.substring(0, methodEnd);
+        clsMethod = clsMethod.replace("::", ".");
         int line = frame.getLine();
         if (line < 0) {
             return clsMethod;
@@ -119,7 +133,10 @@ public final class JavaFrameDisplayer implements FrameDisplayer {
             methodEnd = functionName.length();
         }
         if (methodEnd > 0) {
-            int methodStart = functionName.lastIndexOf('.', methodEnd);
+            int methodStart = functionName.indexOf("::");
+            if (methodStart < 0) {
+                methodStart = functionName.lastIndexOf('.', methodEnd);
+            }
             if (methodStart > 0) {
                 String className = functionName.substring(0, methodStart);
                 URI uri = findClassURI(sourcePath, className);
diff --git a/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaVariablesDisplayer.java b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaVariablesDisplayer.java
index a4009387e5..f0e2755265 100644
--- a/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaVariablesDisplayer.java
+++ b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/JavaVariablesDisplayer.java
@@ -25,16 +25,21 @@ import java.nio.charset.CharsetDecoder;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import static org.netbeans.modules.java.nativeimage.debugger.displayer.Utils.findChild;
+import static org.netbeans.modules.java.nativeimage.debugger.displayer.Utils.getVarsByName;
+import static org.netbeans.modules.java.nativeimage.debugger.displayer.Utils.quoteJavaTypes;
 
 import org.netbeans.modules.nativeimage.api.debug.EvaluateException;
 import org.netbeans.modules.nativeimage.api.debug.NIDebugger;
 import org.netbeans.modules.nativeimage.api.debug.NIFrame;
 import org.netbeans.modules.nativeimage.api.debug.NIVariable;
 import org.netbeans.modules.nativeimage.spi.debug.filters.VariableDisplayer;
+import org.openide.util.NbBundle;
 
 /**
  *
@@ -42,22 +47,29 @@ import org.netbeans.modules.nativeimage.spi.debug.filters.VariableDisplayer;
  */
 public final class JavaVariablesDisplayer implements VariableDisplayer {
 
-    private static final String HUB = "__hub__";
-    private static final String ARRAY = "__array__";
-    private static final String ARRAY_LENGTH = "__length__";
-    private static final String COMPRESSED_REF_REFIX = "_z_.";
-    private static final String PUBLIC = "public";
-    private static final String STRING_VALUE = "value";
-    private static final String STRING_CODER = "coder";
-    private static final String HASH = "hash";
-    private static final String NAME = "name";
-    private static final String UNSET = "<optimized out>";
+    private static final String HUB = "__hub__";                // NOI18N
+    private static final String ARRAY = "__array__";            // NOI18N
+    private static final String ARRAY_LENGTH = "__length__";    // NOI18N
+    private static final String ARRAY_LENGTH_CE = "len";        // NOI18N
+    private static final String ARRAY_DATA_CE = "data";         // NOI18N
+    private static final String OBJ_HEADER_CE = "_objhdr";      // NOI18N
+    private static final String COMPRESSED_REF_REFIX = "_z_.";  // NOI18N
+    static final String PUBLIC = "public";              // NOI18N
+    static final String PRIVATE = "private";            // NOI18N
+    private static final String PROTECTED = "protected";        // NOI18N
+    private static final String STRING_VALUE = "value";         // NOI18N
+    private static final String STRING_CODER = "coder";         // NOI18N
+    private static final String HASH = "hash";                  // NOI18N
+    private static final String NAME = "name";                  // NOI18N
+    private static final String UNSET = "<optimized out>";      // NOI18N
 
     private static final String[] STRING_TYPES = new String[] { String.class.getName(), StringBuilder.class.getName(), StringBuffer.class.getName() };
 
     // Variable names with this prefix contain space-separated variable name and expression path
     private static final String PREFIX_VAR_PATH = "{ ";
 
+    private static final Logger LOG = Logger.getLogger(JavaVariablesDisplayer.class.getName());
+
     private NIDebugger debugger;
     private final Map<NIVariable, String> variablePaths = Collections.synchronizedMap(new WeakHashMap<>());
 
@@ -122,15 +134,42 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
                     if (likeString) {
                         displayedVar = new StringVar(var, name, path, type, isString ? null : subChildren);
                     } else {
+                        DynamicHub hub;
                         if (children.length == 1 && PUBLIC.equals(children[0].getName())) {
                             // Object children
-                            displayedVar = new ObjectVar(var, name, path, subChildren);
+                            displayedVar = new ObjectVarEE(var, name, path, subChildren);
+                        } else if ((hub = DynamicHub.find(var)) != null) {
+                            NIVariable objectVar = null;
+                            DynamicHub.HubType hubType = hub.getType();
+                            if (hubType != null) {
+                                switch (hubType) {
+                                    case OBJECT:
+                                        objectVar = new ObjectVarCE(var, name, path, children, hub);
+                                        break;
+                                    case ARRAY:
+                                        NIVariable lengthVar = findChild(children, PUBLIC, ARRAY_LENGTH_CE);
+                                        NIVariable dataVar = findChild(children, PUBLIC, ARRAY_DATA_CE);
+                                        if (lengthVar != null || dataVar != null) {
+                                            objectVar = new ArrayVarCE(var, name, lengthVar, dataVar, hub);
+                                            break;
+                                        }
+                                }
+                            }
+                            if (objectVar != null) {
+                                displayedVar = objectVar;
+                            } else {
+                                // ordinary var:
+                                displayedVar = new Var(var, name, path);
+                            }
                         } else {
                             displayedVar = new Var(var, name, path);
                         }
                     }
                 }
             }
+            if (LOG.isLoggable(Level.FINE)) {
+                LOG.fine(var.getName() + " => " + displayedVar + ((displayedVar != null) ?  "[" + displayedVar.getName() + "]" : ""));
+            }
             if (displayedVar != var) {
                 synchronized (variablePaths) {
                     variablePaths.put(displayedVar, variablePaths.get(var));
@@ -155,7 +194,7 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         type = displayType(type);
         for (int i = 0; i < type.length(); i++) {
             char c = type.charAt(i);
-            if (c != '.' && !Character.isJavaIdentifierPart(c)) {
+            if (c != '.' && c != '[' && c != ']' && !Character.isJavaIdentifierPart(c)) {
                 return type.substring(0, i);
             }
         }
@@ -187,21 +226,6 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         }
     }
 
-    private static Map<String, NIVariable> getVarsByName(NIVariable[] vars) {
-        switch (vars.length) {
-            case 0:
-                return Collections.emptyMap();
-            case 1:
-                return Collections.singletonMap(vars[0].getName(), vars[0]);
-            default:
-                Map<String, NIVariable> varsByName = new HashMap<>(vars.length);
-                for (NIVariable var : vars) {
-                    varsByName.put(var.getName(), var);
-                }
-                return varsByName;
-        }
-    }
-
     private static NIVariable[] restrictChildren(NIVariable[] children, int from, int to) {
         if (from > 0 || to < children.length) {
             to = Math.min(to, children.length);
@@ -249,7 +273,7 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         return name;
     }
 
-    private String readArray(NIVariable lengthVariable, int itemSize) {
+    private String readArrayEE(NIVariable lengthVariable, int itemSize) {
         int length = Integer.parseInt(lengthVariable.getValue());
         String expressionPath = getExpressionPath(lengthVariable);
         if (expressionPath != null && !expressionPath.isEmpty()) {
@@ -259,14 +283,13 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         return null;
     }
 
-    private String readArray(NIVariable lengthVariable, int offset, int itemSize) {
-        int length = Integer.parseInt(lengthVariable.getValue());
-        String expressionPath = getExpressionPath(lengthVariable);
-        if (expressionPath != null && !expressionPath.isEmpty()) {
-            String addressExpr = "&" + expressionPath;
-            return debugger.readMemory(addressExpr, 4 + offset, length * itemSize); // length has 4 bytes
+    private String readArrayCE(String arrayPath, int length, int itemSize) {
+        if (arrayPath != null && !arrayPath.isEmpty()) {
+            String addressExpr = "&" + arrayPath;
+            return debugger.readMemory(addressExpr, 0, length * itemSize);
+        } else {
+            return null;
         }
-        return null;
     }
 
     private static NIVariable[] getObjectChildren(NIVariable[] children, int from, int to) {
@@ -289,15 +312,6 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         return restrictChildren(children, from, to);
     }
 
-    private static NIVariable findChild(String name, NIVariable[] children) {
-        for (NIVariable var : children) {
-            if (name.equals(var.getName())) {
-                return var;
-            }
-        }
-        return null;
-    }
-
     private static boolean isPrimitiveArray(String type) {
         int i = type.indexOf(' ');
         if (i < 0) {
@@ -322,6 +336,7 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
     private String getExpressionPath(NIVariable var) {
         String path = var.getExpressionPath();
         if (!path.isEmpty()) {
+            path = quoteJavaTypes(path);
             return path;
         } else {
             return createExpressionPath(var);
@@ -340,7 +355,7 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
             return path;
         } else {
             String parentPath = createExpressionPath(parent);
-            if (PUBLIC.equals(path)) {
+            if (PUBLIC.equals(path) || PRIVATE.equals(path) || path.contains(" ")) {
                 return parentPath;
             } else {
                 return parentPath + '.' + path;
@@ -372,6 +387,14 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         @Override
         public String getValue() {
             NIVariable pub = getVarsByName(var.getChildren()).get(PUBLIC);
+            if (pub != null && getVarsByName(pub.getChildren()).get(HUB) != null) {
+                return getValueEE(pub);
+            } else {
+                return getValueCE();
+            }
+        }
+
+        private String getValueEE(NIVariable pub) {
             Map<String, NIVariable> varChildren = getVarsByName(pub.getChildren());
             Map<String, NIVariable> arrayInfo = getVarsByName(varChildren.get(STRING_VALUE).getChildren());
             arrayInfo = getVarsByName(arrayInfo.get(PUBLIC).getChildren());
@@ -379,13 +402,72 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
             NIVariable lengthVariable = arrayInfo.get(ARRAY_LENGTH);
             String lengthStr = lengthVariable.getValue();
             if (lengthStr.isEmpty()) {
-                return "";
+                return "?";
             }
             int length = Integer.parseInt(lengthStr);
             if (length <= 0) {
-                return "";
+                return "?";
+            }
+            NIVariable coderVar = varChildren.get(STRING_CODER);
+            int coder = parseCoder(coderVar);
+            String hexArray = readArrayEE(lengthVariable, 2);
+            if (hexArray != null) {
+                return parseStringFromHEX(hexArray, length, coder);
+            } else { // legacy code for older gdb version (less than 10.x)
+                String arrayExpression = JavaVariablesDisplayer.this.getExpressionPath(arrayVariable);
+                return parseStringFromArray(arrayExpression, length, coder);
+            }
+        }
+
+        private String getValueCE() {
+            Map<String, NIVariable> varPrivChildren = getVarsByName(var.getChildren());
+            NIVariable priv = varPrivChildren.get(PRIVATE);
+            if (priv == null) {
+                NIVariable strVar = varPrivChildren.get(String.class.getName());
+                if (strVar != null) {
+                    priv = getVarsByName(strVar.getChildren()).get(PRIVATE);
+                }
+                if (priv == null) {
+                    return "?";
+                }
             }
+            Map<String, NIVariable> varChildren = getVarsByName(priv.getChildren());
+            NIVariable value = varChildren.get(STRING_VALUE);
             NIVariable coderVar = varChildren.get(STRING_CODER);
+            int coder = parseCoder(coderVar);
+            if (value == null || value.getNumChildren() == 0) {
+                return "?";
+            }
+            NIVariable valueTypeChild = value.getChildren()[0];
+            NIVariable valuePublic = getVarsByName(valueTypeChild.getChildren()).get(PUBLIC);
+            if (valuePublic == null) {
+                return "";
+            }
+            Map<String, NIVariable> arrayChildren = getVarsByName(valuePublic.getChildren());
+            NIVariable lengthVar = arrayChildren.get(ARRAY_LENGTH_CE);
+            NIVariable dataVar = arrayChildren.get(ARRAY_DATA_CE);
+            if (lengthVar == null || dataVar == null) {
+                return "?";
+            }
+            String lengthStr = lengthVar.getValue();
+            if (lengthStr.isEmpty()) {
+                return "";
+            }
+            int length = Integer.parseInt(lengthStr);
+            String arrayPath = JavaVariablesDisplayer.this.getExpressionPath(value);
+            String hexArray = null;
+            if (arrayPath != null && !arrayPath.isEmpty()) {
+                arrayPath += "." + ARRAY_DATA_CE;
+                hexArray = readArrayCE(arrayPath, length, 2);
+            }
+            if (hexArray != null) {
+                return parseStringFromHEX(hexArray, length, coder);
+            } else { // legacy code for older gdb version (less than 10.x)
+                return parseStringFromArray(arrayPath, length, coder);
+            }
+        }
+
+        private int parseCoder(NIVariable coderVar) {
             int coder = -1;
             if (coderVar != null) {
                 String coderStr = coderVar.getValue();
@@ -398,47 +480,7 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
                 } catch (NumberFormatException ex) {
                 }
             }
-            String hexArray = readArray(lengthVariable, 0, 2);
-            if (hexArray != null) {
-                switch (coder) {
-                    case 0: // Compressed String on JDK 9+
-                        return parseLatin1(hexArray, length);
-                    case 1: // UTF-16 String on JDK 9+
-                        return parseUTF16(hexArray, length/2);
-                    default: // UTF-16 String on JDK 8
-                        return parseUTF16(hexArray, length);
-                }
-            } else { // legacy code for older gdb version (less than 10.x)
-                String arrayExpression = JavaVariablesDisplayer.this.getExpressionPath(arrayVariable); //getArrayExpression(arrayVariable);
-                NIFrame frame = var.getFrame();
-                try {
-                    NIVariable charVar = debugger.evaluate(arrayExpression + "[0]", null, frame);
-                    if ("byte".equals(charVar.getType())) {
-                        // bytes to be parsed to String
-                        switch (coder) {
-                            case 0: // Compressed String on JDK 9+
-                                return parseLatin1(arrayExpression, frame, length);
-                            case 1: // UTF-16 String on JDK 9+
-                                return parseUTF16(arrayExpression, frame, length/2);
-                            default: // UTF-16 String on JDK 8
-                                return parseUTF16(arrayExpression, frame, length);
-                        }
-                    } else {
-                        char[] characters = new char[length];
-                        for(int i = 0; ; ) {
-                            String charStr = charVar.getValue();
-                            characters[i] = parseCharacter(charStr);
-                            if (++i >= length) {
-                                break;
-                            }
-                            charVar = debugger.evaluate(arrayExpression + "[" + i + "]", null, frame);
-                        }
-                        return new String(characters);
-                    }
-                } catch (EvaluateException ex) {
-                    return ex.getLocalizedMessage();
-                }
-            }
+            return coder;
         }
 
         private char parseCharacter(String charValue) {
@@ -510,6 +552,17 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
             }
         }
 
+        private String parseStringFromHEX(String hexArray, int length, int coder) {
+            switch (coder) {
+                case 0: // Compressed String on JDK 9+
+                    return parseLatin1(hexArray, length);
+                case 1: // UTF-16 String on JDK 9+
+                    return parseUTF16(hexArray, length/2);
+                default: // UTF-16 String on JDK 8
+                    return parseUTF16(hexArray, length);
+            }
+        }
+
         private String parseUTF16(String hexArray, int length) {
             CharsetDecoder cd = Charset.forName("utf-16").newDecoder(); // NOI18N
             ByteBuffer buffer = ByteBuffer.allocate(2);
@@ -558,6 +611,37 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
             return (byte) (Integer.parseInt(hex, 16) & 0xFF);
         }
 
+        private String parseStringFromArray(String arrayExpression, int length, int coder) {
+            NIFrame frame = var.getFrame();
+            try {
+                NIVariable charVar = debugger.evaluate(arrayExpression + "[0]", null, frame);
+                if ("byte".equals(charVar.getType())) {
+                    // bytes to be parsed to String
+                    switch (coder) {
+                        case 0: // Compressed String on JDK 9+
+                            return parseLatin1(arrayExpression, frame, length);
+                        case 1: // UTF-16 String on JDK 9+
+                            return parseUTF16(arrayExpression, frame, length/2);
+                        default: // UTF-16 String on JDK 8
+                            return parseUTF16(arrayExpression, frame, length);
+                    }
+                } else {
+                    char[] characters = new char[length];
+                    for(int i = 0; ; ) {
+                        String charStr = charVar.getValue();
+                        characters[i] = parseCharacter(charStr);
+                        if (++i >= length) {
+                            break;
+                        }
+                        charVar = debugger.evaluate(arrayExpression + "[" + i + "]", null, frame);
+                    }
+                    return new String(characters);
+                }
+            } catch (EvaluateException ex) {
+                return ex.getLocalizedMessage();
+            }
+        }
+
         private String parseUTF16(String arrayExpression, NIFrame frame, int length) throws EvaluateException {
             CharsetDecoder cd = Charset.forName("utf-16").newDecoder(); // NOI18N
             ByteBuffer buffer = ByteBuffer.allocate(2);
@@ -727,12 +811,126 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
 
     }
 
-    private class ObjectVar extends AbstractVar {
+    private class ArrayVarCE extends AbstractVar {
 
-        private final NIVariable[] children;
+        private final NIVariable lengthVariable;
+        private final int length;
+        private final NIVariable array;
+
+        ArrayVarCE(NIVariable var, String name, NIVariable lengthVariable, NIVariable dataVar, DynamicHub hub) {
+            super(var, name, "");
+            this.lengthVariable = lengthVariable;
+            int arrayLength;
+            try {
+                arrayLength = Integer.parseInt(lengthVariable.getValue());
+            } catch (NumberFormatException ex) {
+                arrayLength = 0;
+            }
+            this.length = arrayLength;
+            this.array = dataVar;
+        }
+
+        @Override
+        public NIFrame getFrame() {
+            return var.getFrame();
+        }
+
+        @Override
+        public NIVariable getParent() {
+            return var.getParent();
+        }
+
+        @Override
+        public String getType() {
+            return displayType(var.getType());
+        }
+
+        @Override
+        public String getValue() {
+            String value = var.getValue();
+            if (value.startsWith("@")) {
+                value = getType() + value;
+            }
+            return value + "(length="+length+")";
+        }
+
+        @Override
+        public int getNumChildren() {
+            return length;
+        }
+
+        @Override
+        public NIVariable[] getChildren(int from, int to) {
+            if (from >= 0) {
+                to = Math.min(to, length);
+            } else {
+                from = 0;
+                to = length;
+            }
+            if (from >= to) {
+                return new NIVariable[]{};
+            }
+
+            String arrayAddress = null;
+            if (isPrimitiveArray(array.getType())) {
+                String expressionPath = JavaVariablesDisplayer.this.getExpressionPath(lengthVariable);
+                if (expressionPath != null && !expressionPath.isEmpty()) {
+                    String addressExpr = "&" + expressionPath;
+                    NIVariable addressVariable;
+                    try {
+                        addressVariable = debugger.evaluate(addressExpr, null, lengthVariable.getFrame());
+                    } catch (EvaluateException ex) {
+                        addressVariable = null;
+                    }
+                    if (addressVariable != null) {
+                        String address = addressVariable.getValue();
+                        address = address.toLowerCase();
+                        if (address.startsWith("0x")) {
+                            arrayAddress = address;
+                        }
+                    }
+                }
+            }
+            NIVariable[] elements = new NIVariable[to - from];
+            try {
+                if (arrayAddress != null) {
+                    int offset = (getTypeSize(getType()) == 8) ? 8 : 4;
+                    String itemExpression = "*(((" + getSimpleType(getType()) + "*)(" + arrayAddress + "+"+offset+"))+";
+                    int size = getTypeSize(getType());
+                    for (int i = from; i < to; i++) {
+                        String expr = itemExpression + i + ")";
+                        NIVariable element = debugger.evaluate(expr, Integer.toString(i), var.getFrame());
+                        // When gdb could retrieve variable address, it did resolve the expression path.
+                        // Thus there is no need to remember it in variablePaths.
+                        elements[i - from] = element;
+                    }
+                } else {
+                    String arrayExpression = JavaVariablesDisplayer.this.getExpressionPath(array);
+                    for (int i = from; i < to; i++) {
+                        String expr = arrayExpression + "[" + i + "]";
+                        String namePath = PREFIX_VAR_PATH + Integer.toString(i) + ' ' + expr;
+                        NIVariable element = debugger.evaluate(expr, namePath, var.getFrame());
+                        variablePaths.put(element, expr);
+                        elements[i - from] = element;
+                    }
+                }
+            } catch (EvaluateException ex) {
+                return new NIVariable[]{};
+            }
+            return elements;
+        }
+
+    }
 
-        ObjectVar(NIVariable var, String name, String path, NIVariable[] children) {
+    private class ObjectVarEE extends AbstractVar {
+
+        protected final NIVariable[] children;
+
+        ObjectVarEE(NIVariable var, String name, String path, NIVariable[] children) {
             super(var, name, path);
+            if (children == null) {
+                throw new NullPointerException("Null children.");
+            }
             this.children = children;
         }
 
@@ -778,11 +976,9 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
             return getObjectChildren(children, from, to);
         }
 
-        private String findRuntimeType() {
-            NIVariable hub = findChild(HUB, children);
-            if (hub != null) {
-                NIVariable pub = findChild(PUBLIC, hub.getChildren());
-                NIVariable nameVar = findChild(NAME, pub.getChildren());
+        protected String findRuntimeType() {
+            if (children.length > 0) {
+                NIVariable nameVar = findChild(children, HUB, PUBLIC, NAME);
                 if (nameVar != null) {
                     String name = new StringVar(nameVar, varName, varPath, null, null).getValue();
                     if (!name.isEmpty()) {
@@ -794,6 +990,135 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         }
     }
 
+    private class ObjectVarCE extends ObjectVarEE {
+
+        private final DynamicHub hub;
+        private NIVariable[] members;
+
+        ObjectVarCE(NIVariable var, String name, String path, NIVariable[] children, DynamicHub hub) {
+            super(var, name, path, children);
+            this.hub = hub;
+        }
+
+        @Override
+        public int getNumChildren() {
+            return getMemberChildren().length;
+        }
+
+        @Override
+        public NIVariable[] getChildren(int from, int to) {
+            return getMemberChildren();
+        }
+
+        @Override
+        protected String findRuntimeType() {
+            NIVariable nameVar = hub.findClassNameVar();
+            if (nameVar != null) {
+                String name = new StringVar(nameVar, varName, varPath, null, null).getValue();
+                if (!name.isEmpty()) {
+                    return name;
+                }
+            }
+            return var.getType();
+        }
+
+        private synchronized NIVariable[] getMemberChildren() {
+            if (members == null) {
+                members = computeMembers(children);
+            }
+            return members;
+        }
+
+    }
+
+    private NIVariable[] computeMembers(NIVariable[] children) {
+        Map<String, NIVariable> varsByName = getVarsByName(children);
+        NIVariable[] vars = new NIVariable[] { varsByName.get(PRIVATE), varsByName.get(PROTECTED), varsByName.get(PUBLIC) };
+        List<NIVariable> collected = new ArrayList<>();
+        for (NIVariable folder : vars) {
+            if (folder != null) {
+                for (NIVariable v : folder.getChildren()) {
+                    collected.add(v);
+                }
+            }
+        }
+        NIVariable inherited = createInherited(children);
+        if (collected.isEmpty()) {
+            if (inherited == null) {
+                return new NIVariable[]{};
+            } else {
+                return inherited.getChildren();
+            }
+        }
+        if (inherited != null) {
+            collected.add(inherited);
+        }
+        return collected.toArray(new NIVariable[collected.size()]);
+    }
+
+    private NIVariable createInherited(NIVariable[] children) {
+        if (children.length == 0) {
+            return null;
+        }
+        NIVariable superClass = children[0];
+        if (superClass.getName().equals(OBJ_HEADER_CE)) {
+            return null;
+        }
+        NIVariable[] superChildren = superClass.getChildren();
+        if (superChildren.length == 1) {
+            // There are no fields here
+            return createInherited(superChildren);
+        }
+        return new Inherited(superClass);
+    }
+
+    private class Inherited extends AbstractVar {
+
+        private NIVariable[] members;
+
+        @NbBundle.Messages({"# {0} - Name of class from which are the members inherited.", "LBL_Inherited=<Inherited from {0}>"})
+        Inherited(NIVariable typeVar) {
+            super(typeVar, Bundle.LBL_Inherited(typeVar.getName()), "");
+        }
+
+        @Override
+        public String getType() {
+            return "";
+        }
+
+        @Override
+        public String getValue() {
+            return "";
+        }
+
+        @Override
+        public NIVariable getParent() {
+            return var.getParent();
+        }
+
+        @Override
+        public int getNumChildren() {
+            return getMemberChildren().length;
+        }
+
+        @Override
+        public NIVariable[] getChildren(int from, int to) {
+            return getMemberChildren();
+        }
+
+        private synchronized NIVariable[] getMemberChildren() {
+            if (members == null) {
+                members = computeMembers(var.getChildren());
+            }
+            return members;
+        }
+
+        @Override
+        public NIFrame getFrame() {
+            return var.getFrame();
+        }
+    }
+
     private class Var extends AbstractVar {
 
         Var(NIVariable var, String name, String path) {
@@ -844,6 +1169,9 @@ public final class JavaVariablesDisplayer implements VariableDisplayer {
         protected final String varPath;
 
         AbstractVar(NIVariable var, String varName, String varPath) {
+            if (var == null) {
+                throw new NullPointerException("Null variable.");
+            }
             this.var = var;
             this.varName = varName;
             this.varPath = varPath;
diff --git a/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/Utils.java b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/Utils.java
new file mode 100644
index 0000000000..1b154cf554
--- /dev/null
+++ b/java/java.nativeimage.debugger/src/org/netbeans/modules/java/nativeimage/debugger/displayer/Utils.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.java.nativeimage.debugger.displayer;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.modules.nativeimage.api.debug.NIVariable;
+
+/**
+ * Various static utilities.
+ */
+final class Utils {
+
+    private Utils() {
+    }
+
+    static Map<String, NIVariable> getVarsByName(NIVariable[] vars) {
+        switch (vars.length) {
+            case 0:
+                return Collections.emptyMap();
+            case 1:
+                return Collections.singletonMap(vars[0].getName(), vars[0]);
+            default:
+                Map<String, NIVariable> varsByName = new HashMap<>(vars.length);
+                for (NIVariable var : vars) {
+                    varsByName.put(var.getName(), var);
+                }
+                return Collections.unmodifiableMap(varsByName);
+        }
+    }
+
+    @CheckForNull
+    static NIVariable findChild(NIVariable[] children, String... names) {
+        NIVariable ch = null;
+        for (String name : names) {
+            if (ch != null) {
+                children = ch.getChildren();
+            }
+            ch = findChild(name, children);
+            if (ch == null) {
+                return null;
+            }
+        }
+        return ch;
+    }
+
+    @CheckForNull
+    private static NIVariable findChild(String name, NIVariable[] children) {
+        for (NIVariable var : children) {
+            if (name.equals(var.getName())) {
+                return var;
+            }
+        }
+        return null;
+    }
+
+    // Quote all types which follow the class keyword and variables having dots in name.
+    // This is crucial for types containing dots like Java class names.
+    static String quoteJavaTypes(String expr) {
+        final String clazz = "(class "; // NOI18N
+        int i = expr.indexOf(clazz);
+        if (i >= 0) {
+            StringBuilder quoted = new StringBuilder();
+            int j = 0;
+            do {
+                i += clazz.length();
+                quoted.append(quoteJavaVarNames(expr.substring(j, i)));
+                j = expr.indexOf(')', i);
+                if (j > 0) {
+                    while (expr.charAt(j - 1) == '*') {
+                        j--;
+                    }
+                    quoted.append('\'');
+                    quoted.append(expr.substring(i, j));
+                    quoted.append('\'');
+                } else {
+                    // Inconsistent parenthesis
+                    return expr;
+                }
+                i = expr.indexOf(clazz, j);
+            } while (i > 0);
+            quoted.append(quoteJavaVarNames(expr.substring(j)));
+            return quoted.toString();
+        } else {
+            return expr;
+        }
+    }
+
+    // Variables that contain dots are quoted
+    private static String quoteJavaVarNames(String expr) {
+        int i = expr.indexOf('.');
+        if (i > 0) {
+            StringBuilder quoted = new StringBuilder();
+            int i0 = 0;
+            do {
+                char c = 0;
+                int i1 = i - 1;
+                while (i1 >= i0 && ((c = expr.charAt(i1)) == '.' || Character.isJavaIdentifierPart(c))) {
+                    i1--;
+                }
+                if (i1 >= i0) {
+                    i1++;
+                    c = expr.charAt(i1);
+                }
+                if (!Character.isJavaIdentifierStart(c)) {
+                    i++;
+                    quoted.append(expr.substring(i0, i));
+                    i0 = i;
+                    continue;
+                }
+                int i2 = i + 1;
+                while (i2 < expr.length() && ((c = expr.charAt(i2)) == '.' || Character.isJavaIdentifierPart(c))) {
+                    i2++;
+                }
+                quoted.append(expr.substring(i0, i1));
+                quoted.append('\'');
+                quoted.append(expr.substring(i1, i2));
+                quoted.append('\'');
+                i0 = i2;
+            } while ((i = expr.indexOf('.', i0)) > 0);
+            quoted.append(expr.substring(i0));
+            return quoted.toString();
+        } else {
+            return expr;
+        }
+    }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists