I trace down to the while loop in nxml-forward-single-balanced-item:

(defun nxml-forward-single-balanced-item ()
  (condition-case err
      (goto-char (let ((end (nxml-token-after)))
  (save-excursion
    (while (eq xmltok-type 'space)
      (goto-char end)
      (setq end (nxml-token-after)))
    (cond ((/= (point) xmltok-start)

In my test xml file, when the last comment char is deleted, `end' will be 65, then (nxml-token-after) also returns 65  , so this is a endless loop.