diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ExtUtils.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ExtUtils.java
index 1f787dbc..431234bd 100644
--- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ExtUtils.java
+++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/ExtUtils.java
@@ -20,13 +20,16 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IClasspathContainer;
 import org.eclipse.jdt.core.IJarEntryResource;
+import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.core.JarEntryDirectory;
 import org.eclipse.jdt.internal.core.JarEntryFile;
+import org.eclipse.jdt.launching.JavaRuntime;
 import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
 
 public final class ExtUtils {
@@ -104,6 +107,18 @@ public static IPath removeProjectSegment(String projectElementName, IPath path)
         return path;
     }
 
+    public static URI getContainerURI(IJavaProject javaProject, IClasspathContainer container) throws CoreException {
+        switch (container.getKind()) {
+        case IClasspathContainer.K_DEFAULT_SYSTEM: // JRE Container
+        case IClasspathContainer.K_SYSTEM:
+            return JavaRuntime.getVMInstall(javaProject).getInstallLocation().toURI();
+        case IClasspathContainer.K_APPLICATION: // Plugin Container, Maven Container, etc
+            return null; // TODO: find out a good way to detect these containers' uri
+        default: // Persistent container (e.g. /src/main/java)
+            return container.getPath().toFile().toURI();
+        }
+    }
+
     private static JarEntryFile findFileInJar(JarEntryDirectory directory, String path) {
         for (IJarEntryResource child : directory.getChildren()) {
             if (child instanceof JarEntryFile && child.getFullPath().toPortableString().equals(path)) {
diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java
index 3130fda1..b3cb3e8b 100644
--- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java
+++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/PackageCommand.java
@@ -175,9 +175,9 @@ public static List<PackageNode> resolvePath(List<Object> arguments, IProgressMon
                     IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) packageFragment.getParent();
                     PackageNode rootNode = null;
 
-                    rootNode = new PackageRootNode(
+                    rootNode = new PackageRootNode(pkgRoot,
                             ExtUtils.removeProjectSegment(packageFragment.getJavaProject().getElementName(), pkgRoot.getPath()).toPortableString(),
-                            pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind());
+                            NodeKind.PACKAGEROOT);
 
                     result.add(PackageNode.createNodeForProject(packageFragment));
                     result.add(rootNode);
@@ -209,8 +209,8 @@ private static List<PackageNode> getParentAncestorNodes(IResource element) throw
             IJavaElement javaElement = JavaCore.create(element);
             if (javaElement instanceof IPackageFragmentRoot) {
                 IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) javaElement;
-                nodeList.add(0, new PackageRootNode(element.getProjectRelativePath().toPortableString(), pkgRoot.getPath().toPortableString(),
-                        NodeKind.PACKAGEROOT, pkgRoot.getKind()));
+                nodeList.add(0, new PackageRootNode(pkgRoot,
+                        element.getProjectRelativePath().toPortableString(), NodeKind.PACKAGEROOT));
                 nodeList.add(0, PackageNode.createNodeForProject(javaElement));
                 return nodeList;
             } else if (javaElement instanceof IPackageFragment) {
@@ -280,8 +280,7 @@ private static List<PackageNode> getPackageFragmentRoots(PackageParams query, IP
                         if (fragmentRoot.getKind() == IPackageFragmentRoot.K_SOURCE) {
                             displayName = ExtUtils.removeProjectSegment(javaProject.getElementName(), fragmentRoot.getPath()).toPortableString();
                         }
-                        PackageRootNode node = new PackageRootNode(displayName, fragmentRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT,
-                                fragmentRoot.getKind());
+                        PackageRootNode node = new PackageRootNode(fragmentRoot, displayName, NodeKind.PACKAGEROOT);
                         children.add(node);
                         if (fragmentRoot instanceof JrtPackageFragmentRoot) {
                             node.setModuleName(fragmentRoot.getModuleDescription().getElementName());
@@ -440,7 +439,14 @@ private static List<PackageNode> convertToPackageNode(Object[] rootContent, IPac
         List<PackageNode> result = new ArrayList<>();
         for (Object root : rootContent) {
             if (root instanceof IPackageFragment) {
-                result.add(PackageNode.createNodeForPackageFragment((IPackageFragment) root));
+                IPackageFragment fragment = (IPackageFragment) root;
+                PackageNode entry = PackageNode.createNodeForPackageFragment(fragment);
+                if (fragment.getResource() != null) {
+                    entry.setUri(fragment.getResource().getLocationURI().toString());
+                } else {
+                    entry.setUri(fragment.getPath().toFile().toURI().toString());
+                }
+                result.add(entry);
             } else if (root instanceof IClassFile) {
                 IClassFile classFile = (IClassFile) root;
                 PackageNode entry = new PackageNode(classFile.getElementName(), null, NodeKind.TYPEROOT);
diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java
index 2b17d375..2a363f7f 100644
--- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java
+++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageNode.java
@@ -11,6 +11,7 @@
 
 package com.microsoft.jdtls.ext.core.model;
 
+import java.net.URI;
 import java.util.List;
 
 import org.eclipse.core.resources.IFile;
@@ -133,11 +134,11 @@ public static PackageNode createNodeForPackageFragmentRoot(IPackageFragmentRoot
             if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
                 return createNodeForClasspathVariable(entry);
             } else {
-                return new PackageRootNode(pkgRoot.getElementName(), pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind());
+                return new PackageRootNode(pkgRoot, pkgRoot.getElementName(), NodeKind.PACKAGEROOT);
             }
         } else {
-            return new PackageRootNode(ExtUtils.removeProjectSegment(pkgRoot.getJavaProject().getElementName(), pkgRoot.getPath()).toPortableString(),
-                    pkgRoot.getPath().toPortableString(), NodeKind.PACKAGEROOT, pkgRoot.getKind());
+            return new PackageRootNode(pkgRoot,
+                    ExtUtils.removeProjectSegment(pkgRoot.getJavaProject().getElementName(), pkgRoot.getPath()).toPortableString(), NodeKind.PACKAGEROOT);
         }
     }
 
@@ -161,17 +162,21 @@ public static PackageNode createNodeForClasspathEntry(IClasspathEntry classpathE
                 container = JavaCore.getClasspathContainer(entry.getPath(), javaProject);
             }
             if (container != null) {
-                switch (nodeKind) {
-                case CONTAINER:
-                    return new ContainerNode(container.getDescription(), container.getPath().toPortableString(), nodeKind, entry.getEntryKind());
-                case PACKAGEROOT:
+                PackageNode node = null;
+                if (nodeKind == NodeKind.CONTAINER) {
+                    node = new ContainerNode(container.getDescription(), container.getPath().toPortableString(), nodeKind, entry.getEntryKind());
+                    final URI containerURI = ExtUtils.getContainerURI(javaProject, container);
+                    node.setUri(containerURI != null ? containerURI.toString() : null);
+                } else if (nodeKind == NodeKind.PACKAGEROOT) { // ClasspathEntry for referenced jar files
                     // Use package name as package root name
                     String[] pathSegments = container.getPath().segments();
-                    return new PackageRootNode(pathSegments[pathSegments.length - 1], container.getPath().toPortableString(), nodeKind,
-                            IPackageFragmentRoot.K_BINARY);
-                default:
-                    return null;
+                    node = new PackageRootNode(
+                        pathSegments[pathSegments.length - 1],
+                        container.getPath().toPortableString(),
+                        container.getPath().toFile().toURI().toString(),
+                        nodeKind, IPackageFragmentRoot.K_BINARY);
                 }
+                return node;
             }
         } catch (CoreException e) {
             JdtlsExtActivator.logException("Problems when convert classpath entry to package node ", e);
@@ -201,7 +206,8 @@ public static PackageNode createNodeForClasspathVariable(IClasspathEntry classpa
         IClasspathEntry entry = JavaCore.getResolvedClasspathEntry(classpathEntry);
         String name = classpathEntry.getPath().toPortableString();
         String path = entry.getPath().toPortableString();
-        return new PackageRootNode(name, path, NodeKind.PACKAGEROOT, IPackageFragmentRoot.K_BINARY);
+        String uri = entry.getPath().toFile().toURI().toString();
+        return new PackageRootNode(name, path, uri, NodeKind.PACKAGEROOT, IPackageFragmentRoot.K_BINARY);
     }
 
     public String getName() {
diff --git a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageRootNode.java b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageRootNode.java
index b172c327..d98439dd 100644
--- a/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageRootNode.java
+++ b/jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/model/PackageRootNode.java
@@ -13,17 +13,30 @@
 
 import java.util.Map;
 
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+
 public class PackageRootNode extends PackageNode {
 
     private int entryKind;
 
     private Map<String, String> attributes;
 
-    public PackageRootNode(String name, String path, NodeKind kind, int entryKind) {
+    public PackageRootNode(String name, String path, String uri, NodeKind kind, int entryKind) {
         super(name, path, kind);
+        this.setUri(uri);
         this.entryKind = entryKind;
     }
 
+    public PackageRootNode(IPackageFragmentRoot pkgRoot, String name, NodeKind kind) throws JavaModelException {
+        this(name, pkgRoot.getPath().toPortableString(), null, kind, pkgRoot.getKind());
+        if (pkgRoot.getResource() != null) {
+            this.setUri(pkgRoot.getResource().getLocationURI().toString());
+        } else {
+            this.setUri(pkgRoot.getPath().toFile().toURI().toString());
+        }
+    }
+
     public int getEntryType() {
         return this.entryKind;
     }
diff --git a/package.json b/package.json
index 38882567..d00a44d1 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
     "explorer"
   ],
   "engines": {
-    "vscode": "^1.30.0"
+    "vscode": "^1.31.0"
   },
   "repository": {
     "type": "git",
@@ -83,6 +83,21 @@
           "dark": "images/dark/icon-link.svg",
           "light": "images/light/icon-link.svg"
         }
+      },
+      {
+        "command": "java.view.package.revealFileInOS",
+        "title": "%contributes.commands.java.view.package.revealFileInOS%",
+        "category": "Java"
+      },
+      {
+        "command": "java.view.package.copyFilePath",
+        "title": "%contributes.commands.java.view.package.copyFilePath%",
+        "category": "Java"
+      },
+      {
+        "command": "java.view.package.copyRelativeFilePath",
+        "title": "%contributes.commands.java.view.package.copyRelativeFilePath%",
+        "category": "Java"
       }
     ],
     "configuration": {
@@ -121,6 +136,20 @@
       }
     },
     "menus": {
+      "commandPalette": [
+        {
+          "command": "java.view.package.revealFileInOS",
+          "when": "never"
+        },
+        {
+          "command": "java.view.package.copyFilePath",
+          "when": "never"
+        },
+        {
+          "command": "java.view.package.copyRelativeFilePath",
+          "when": "never"
+        }
+      ],
       "view/title": [
         {
           "command": "java.view.package.refresh",
@@ -147,6 +176,23 @@
           "when": "view == javaDependencyExplorer && config.java.dependency.syncWithFolderExplorer == true",
           "group": "navigation@0"
         }
+      ],
+      "view/item/context": [
+        {
+          "command": "java.view.package.revealFileInOS",
+          "when": "view == javaDependencyExplorer && viewItem =~ /java:.*?\\+uri/",
+          "group": "@1"
+        },
+        {
+          "command": "java.view.package.copyFilePath",
+          "when": "view == javaDependencyExplorer && viewItem =~ /java:.*?\\+uri/",
+          "group": "@2"
+        },
+        {
+          "command": "java.view.package.copyRelativeFilePath",
+          "when": "view == javaDependencyExplorer && viewItem =~ /java:.*?\\+uri/",
+          "group": "@2"
+        }
       ]
     },
     "views": {
diff --git a/package.nls.json b/package.nls.json
index a8bcd4a3..5c252147 100644
--- a/package.nls.json
+++ b/package.nls.json
@@ -7,6 +7,9 @@
   "contributes.commands.java.view.package.changeToHierarchicalPackageView":"Change to hierarchical package representation",
   "contributes.commands.java.view.package.linkWithFolderExplorer":"Synchronize dependency viewer selection with folder explorer",
   "contributes.commands.java.view.package.unlinkWithFolderExplorer":"Desynchronize dependency viewer selection with folder explorer",
+  "contributes.commands.java.view.package.revealFileInOS": "Reveal In Explorer",
+  "contributes.commands.java.view.package.copyFilePath": "Copy Path",
+  "contributes.commands.java.view.package.copyRelativeFilePath": "Copy Relative Path",
   "configuration.java.dependency.title": "Java Dependency Configuration",
   "configuration.java.dependency.showOutline": "Enable show outline in the Java Dependency explorer",
   "configuration.java.dependency.syncWithFolderExplorer": "Synchronize dependency viewer selection with folder explorer",
diff --git a/package.nls.zh.json b/package.nls.zh.json
index 3c9c655a..ee0f600d 100644
--- a/package.nls.zh.json
+++ b/package.nls.zh.json
@@ -7,6 +7,9 @@
   "contributes.commands.java.view.package.changeToHierarchicalPackageView":"将 Java 包显示方式切换为分层显示",
   "contributes.commands.java.view.package.linkWithFolderExplorer":"开启 Java 依赖项资源管理器与当前浏览文件的关联",
   "contributes.commands.java.view.package.unlinkWithFolderExplorer":"关闭 Java 依赖项资源管理器与当前浏览文件的关联",
+  "contributes.commands.java.view.package.revealFileInOS": "打开所在的文件夹",
+  "contributes.commands.java.view.package.copyFilePath": "复制路径",
+  "contributes.commands.java.view.package.copyRelativeFilePath": "复制相对路径",
   "configuration.java.dependency.title": "Java 依赖管理配置",
   "configuration.java.dependency.showOutline": "在 Java 依赖项资源管理器中显示类成员大纲",
   "configuration.java.dependency.syncWithFolderExplorer": "在 Java 依赖项资源管理器中同步关联当前打开的文件",
diff --git a/src/commands.ts b/src/commands.ts
index 430fd354..1e49effe 100644
--- a/src/commands.ts
+++ b/src/commands.ts
@@ -24,6 +24,12 @@ export namespace Commands {
 
     export const VIEW_PACKAGE_OUTLINE = "java.view.package.outline";
 
+    export const VIEW_PACKAGE_REVEAL_FILE_OS = "java.view.package.revealFileInOS";
+
+    export const VIEW_PACKAGE_COPY_FILE_PATH = "java.view.package.copyFilePath";
+
+    export const VIEW_PACKAGE_COPY_RELATIVE_FILE_PATH = "java.view.package.copyRelativeFilePath";
+
     export const JAVA_PROJECT_CREATE = "java.project.create";
 
     export const JAVA_PROJECT_LIST = "java.project.list";
diff --git a/src/views/dependencyDataProvider.ts b/src/views/dependencyDataProvider.ts
index ebdabd75..107a04c7 100644
--- a/src/views/dependencyDataProvider.ts
+++ b/src/views/dependencyDataProvider.ts
@@ -28,6 +28,12 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
 
     constructor(public readonly context: ExtensionContext) {
         context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_REFRESH, (debounce?: boolean) => this.refreshWithLog(debounce)));
+        context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_REVEAL_FILE_OS,
+            (node: INodeData) => commands.executeCommand("revealFileInOS", Uri.parse(node.uri))));
+        context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_COPY_FILE_PATH,
+            (node: INodeData) => commands.executeCommand("copyFilePath", Uri.parse(node.uri))));
+        context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_COPY_RELATIVE_FILE_PATH,
+            (node: INodeData) => commands.executeCommand("copyRelativeFilePath", Uri.parse(node.uri))));
         context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_OPEN_FILE,
             instrumentOperation(Commands.VIEW_PACKAGE_OPEN_FILE, (_operationId, uri) => this.openFile(uri))));
         context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_OUTLINE,