diff --git a/.gitignore b/.gitignore
index 639696a..f43ecf7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,3 +100,5 @@ lib/**/*
 
 # Project specific
 __tests__/__results__
+
+.idea
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..79bdb1b
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+v18.7.0
diff --git a/__tests__/java-stack-trace-element-parser.test.ts b/__tests__/java-stack-trace-element-parser.test.ts
new file mode 100644
index 0000000..6fe1ac2
--- /dev/null
+++ b/__tests__/java-stack-trace-element-parser.test.ts
@@ -0,0 +1,75 @@
+import {parseStackTraceElement} from '../src/parsers/java-junit/java-stack-trace-element-parser'
+
+describe('parseStackTraceLine tests', () => {
+  it('empty line is not parsed', async () => {
+    const line = ''
+    expect(parseStackTraceElement(line)).toBe(undefined)
+  })
+
+  describe('java class', () => {
+    it('simple', async () => {
+      const line =
+        'at org.apache.pulsar.AddMissingPatchVersionTest.testVersionStrings(AddMissingPatchVersionTest.java:29)'
+      expect(parseStackTraceElement(line)).toEqual({
+        tracePath: 'org.apache.pulsar.AddMissingPatchVersionTest.testVersionStrings',
+        fileName: 'AddMissingPatchVersionTest.java',
+        lineStr: '29'
+      })
+    })
+
+    it('inner class', async () => {
+      const line = 'at com.foo.Main$Inner.run(Main.java:29)'
+      expect(parseStackTraceElement(line)).toEqual({
+        tracePath: 'com.foo.Main$Inner.run',
+        fileName: 'Main.java',
+        lineStr: '29'
+      })
+    })
+
+    it('starts with whitespaces', async () => {
+      const line =
+        ' \tat org.apache.pulsar.AddMissingPatchVersionTest.testVersionStrings(AddMissingPatchVersionTest.java:29)'
+      expect(parseStackTraceElement(line)).toEqual({
+        tracePath: 'org.apache.pulsar.AddMissingPatchVersionTest.testVersionStrings',
+        fileName: 'AddMissingPatchVersionTest.java',
+        lineStr: '29'
+      })
+    })
+
+    describe('since Java 9', () => {
+      it('with classloader and module', async () => {
+        // Based on Java 9 StackTraceElement.toString() Doc: https://docs.oracle.com/javase/9/docs/api/java/lang/StackTraceElement.html#toString--
+        const line = 'at com.foo.loader/foo@9.0/com.foo.Main.run(Main.java:101)'
+        expect(parseStackTraceElement(line)).toEqual({
+          classLoader: 'com.foo.loader',
+          moduleNameAndVersion: 'foo@9.0',
+          tracePath: 'com.foo.Main.run',
+          fileName: 'Main.java',
+          lineStr: '101'
+        })
+      })
+
+      it('with classloader', async () => {
+        const line = 'at com.foo.loader//com.foo.Main.run(Main.java:101)'
+        expect(parseStackTraceElement(line)).toEqual({
+          classLoader: 'com.foo.loader',
+          moduleNameAndVersion: undefined,
+          tracePath: 'com.foo.Main.run',
+          fileName: 'Main.java',
+          lineStr: '101'
+        })
+      })
+    })
+  })
+
+  describe('Kotlin class', () => {
+    it('method name containing whitespaces', async () => {
+      const line = 'at com.foo.Main.method with whitespaces(Main.kt:18)'
+      expect(parseStackTraceElement(line)).toEqual({
+        tracePath: 'com.foo.Main.method with whitespaces',
+        fileName: 'Main.kt',
+        lineStr: '18'
+      })
+    })
+  })
+})
diff --git a/dist/index.js b/dist/index.js
index 21c0fe8..19587c3 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -926,6 +926,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
 exports.JavaJunitParser = void 0;
 const path = __importStar(__nccwpck_require__(1017));
 const xml2js_1 = __nccwpck_require__(6189);
+const java_stack_trace_element_parser_1 = __nccwpck_require__(5775);
 const path_utils_1 = __nccwpck_require__(4070);
 const test_results_1 = __nccwpck_require__(2768);
 class JavaJunitParser {
@@ -1053,11 +1054,10 @@ class JavaJunitParser {
     }
     exceptionThrowSource(stackTrace) {
         const lines = stackTrace.split(/\r?\n/);
-        const re = /^at (.*)\((.*):(\d+)\)$/;
         for (const str of lines) {
-            const match = str.match(re);
-            if (match !== null) {
-                const [_, tracePath, fileName, lineStr] = match;
+            const stackTraceElement = (0, java_stack_trace_element_parser_1.parseStackTraceElement)(str);
+            if (stackTraceElement) {
+                const { tracePath, fileName, lineStr } = stackTraceElement;
                 const filePath = this.getFilePath(tracePath, fileName);
                 if (filePath !== undefined) {
                     const line = parseInt(lineStr);
@@ -1110,6 +1110,49 @@ class JavaJunitParser {
 exports.JavaJunitParser = JavaJunitParser;
 
 
+/***/ }),
+
+/***/ 5775:
+/***/ ((__unused_webpack_module, exports) => {
+
+"use strict";
+
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+exports.parseStackTraceElement = void 0;
+// classloader and module name are optional:
+// at <CLASSLOADER>/<MODULE_NAME_AND_VERSION>/<FULLY_QUALIFIED_METHOD_NAME>(<FILE_NAME>:<LINE_NUMBER>)
+// https://github.com/eclipse-openj9/openj9/issues/11452#issuecomment-754946992
+const re = /^\s*at (\S+\/\S*\/)?(.*)\((.*):(\d+)\)$/;
+function parseStackTraceElement(stackTraceLine) {
+    const match = stackTraceLine.match(re);
+    if (match !== null) {
+        const [_, maybeClassLoaderAndModuleNameAndVersion, tracePath, fileName, lineStr] = match;
+        const { classLoader, moduleNameAndVersion } = parseClassLoaderAndModule(maybeClassLoaderAndModuleNameAndVersion);
+        return {
+            classLoader,
+            moduleNameAndVersion,
+            tracePath,
+            fileName,
+            lineStr
+        };
+    }
+    return undefined;
+}
+exports.parseStackTraceElement = parseStackTraceElement;
+function parseClassLoaderAndModule(maybeClassLoaderAndModuleNameAndVersion) {
+    if (maybeClassLoaderAndModuleNameAndVersion) {
+        const res = maybeClassLoaderAndModuleNameAndVersion.split('/');
+        const classLoader = res[0];
+        let moduleNameAndVersion = res[1];
+        if (moduleNameAndVersion === '') {
+            moduleNameAndVersion = undefined;
+        }
+        return { classLoader, moduleNameAndVersion };
+    }
+    return { classLoader: undefined, moduleNameAndVersion: undefined };
+}
+
+
 /***/ }),
 
 /***/ 1113:
diff --git a/src/parsers/java-junit/java-junit-parser.ts b/src/parsers/java-junit/java-junit-parser.ts
index 42b7b08..9925365 100644
--- a/src/parsers/java-junit/java-junit-parser.ts
+++ b/src/parsers/java-junit/java-junit-parser.ts
@@ -3,6 +3,7 @@ import {ParseOptions, TestParser} from '../../test-parser'
 import {parseStringPromise} from 'xml2js'
 
 import {JunitReport, SingleSuiteReport, TestCase, TestSuite} from './java-junit-types'
+import {parseStackTraceElement} from './java-stack-trace-element-parser'
 import {normalizeFilePath} from '../../utils/path-utils'
 
 import {
@@ -146,12 +147,11 @@ export class JavaJunitParser implements TestParser {
 
   private exceptionThrowSource(stackTrace: string): {filePath: string; line: number} | undefined {
     const lines = stackTrace.split(/\r?\n/)
-    const re = /^at (.*)\((.*):(\d+)\)$/
 
     for (const str of lines) {
-      const match = str.match(re)
-      if (match !== null) {
-        const [_, tracePath, fileName, lineStr] = match
+      const stackTraceElement = parseStackTraceElement(str)
+      if (stackTraceElement) {
+        const {tracePath, fileName, lineStr} = stackTraceElement
         const filePath = this.getFilePath(tracePath, fileName)
         if (filePath !== undefined) {
           const line = parseInt(lineStr)
diff --git a/src/parsers/java-junit/java-stack-trace-element-parser.ts b/src/parsers/java-junit/java-stack-trace-element-parser.ts
new file mode 100644
index 0000000..894dd42
--- /dev/null
+++ b/src/parsers/java-junit/java-stack-trace-element-parser.ts
@@ -0,0 +1,44 @@
+export interface StackTraceElement {
+  classLoader: string | undefined
+  moduleNameAndVersion: string | undefined
+  tracePath: string
+  fileName: string
+  lineStr: string
+}
+
+// classloader and module name are optional:
+// at <CLASSLOADER>/<MODULE_NAME_AND_VERSION>/<FULLY_QUALIFIED_METHOD_NAME>(<FILE_NAME>:<LINE_NUMBER>)
+// https://github.com/eclipse-openj9/openj9/issues/11452#issuecomment-754946992
+const re = /^\s*at (\S+\/\S*\/)?(.*)\((.*):(\d+)\)$/
+
+export function parseStackTraceElement(stackTraceLine: string): StackTraceElement | undefined {
+  const match = stackTraceLine.match(re)
+  if (match !== null) {
+    const [_, maybeClassLoaderAndModuleNameAndVersion, tracePath, fileName, lineStr] = match
+    const {classLoader, moduleNameAndVersion} = parseClassLoaderAndModule(maybeClassLoaderAndModuleNameAndVersion)
+    return {
+      classLoader,
+      moduleNameAndVersion,
+      tracePath,
+      fileName,
+      lineStr
+    }
+  }
+  return undefined
+}
+
+function parseClassLoaderAndModule(maybeClassLoaderAndModuleNameAndVersion?: string): {
+  classLoader?: string
+  moduleNameAndVersion?: string
+} {
+  if (maybeClassLoaderAndModuleNameAndVersion) {
+    const res = maybeClassLoaderAndModuleNameAndVersion.split('/')
+    const classLoader = res[0]
+    let moduleNameAndVersion: string | undefined = res[1]
+    if (moduleNameAndVersion === '') {
+      moduleNameAndVersion = undefined
+    }
+    return {classLoader, moduleNameAndVersion}
+  }
+  return {classLoader: undefined, moduleNameAndVersion: undefined}
+}