diff a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this
@@ -23,10 +23,11 @@
  * questions.
  */
 
 package com.sun.tools.javac.model;
 
+import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -41,12 +42,15 @@
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.util.Elements;
 import javax.tools.JavaFileObject;
 import static javax.lang.model.util.ElementFilter.methodsIn;
 
+import com.sun.source.tree.Tree;
 import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacScope;
 import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.api.JavacTrees;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.Compound;
 import com.sun.tools.javac.code.Directive.ExportsDirective;
 import com.sun.tools.javac.code.Directive.ExportsFlag;
 import com.sun.tools.javac.code.Directive.OpensDirective;
@@ -54,30 +58,34 @@
 import com.sun.tools.javac.code.Directive.RequiresDirective;
 import com.sun.tools.javac.code.Directive.RequiresFlag;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.Attr;
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.comp.ReflectMethods;
 import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.processing.PrintingProcessor;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.tree.TreeMaker;
 import com.sun.tools.javac.tree.TreeScanner;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.Name;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.CLASS;
-import com.sun.tools.javac.comp.Attr;
+
 import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.comp.Resolve;
-import com.sun.tools.javac.comp.Resolve.RecoveryLoadClass;
 import com.sun.tools.javac.resources.CompilerProperties.Notes;
+import jdk.internal.java.lang.reflect.code.op.CoreOp;
+
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /**
  * Utility methods for operating on program elements.
  *
@@ -92,14 +100,17 @@
     private final Symtab syms;
     private final Modules modules;
     private final Names names;
     private final Types types;
     private final Enter enter;
+    private final JavacTrees javacTrees;
     private final Attr attr;
     private final Resolve resolve;
+    private final ReflectMethods reflectMethods;
     private final JavacTaskImpl javacTaskImpl;
     private final Log log;
+    private final TreeMaker make;
     private final boolean allowModules;
 
     public static JavacElements instance(Context context) {
         JavacElements instance = context.get(JavacElements.class);
         if (instance == null)
@@ -116,13 +127,16 @@
         names = Names.instance(context);
         types = Types.instance(context);
         enter = Enter.instance(context);
         attr = Attr.instance(context);
         resolve = Resolve.instance(context);
+        javacTrees = JavacTrees.instance(context);
+        reflectMethods = ReflectMethods.instance(context);
         JavacTask t = context.get(JavacTask.class);
         javacTaskImpl = t instanceof JavacTaskImpl taskImpl ? taskImpl : null;
         log = Log.instance(context);
+        make = TreeMaker.instance(context);
         Source source = Source.instance(context);
         allowModules = Feature.MODULES.allowedInSource(source);
     }
 
     @Override @DefinedBy(Api.LANGUAGE_MODEL)
@@ -791,10 +805,42 @@
             case TYP -> ((ClassSymbol) sym).classfile;
             default -> sym.enclClass().classfile;
         };
     }
 
+    @Override @DefinedBy(Api.LANGUAGE_MODEL)
+    public Optional<Object> getBody(ExecutableElement e) {
+        if (e.getModifiers().contains(Modifier.ABSTRACT) ||
+                e.getModifiers().contains(Modifier.NATIVE)) {
+            return Optional.empty();
+        }
+
+        CoreOp.FuncOp funcOp;
+        try {
+            JCMethodDecl methodTree = (JCMethodDecl)getTree(e);
+            JavacScope scope = javacTrees.getScope(javacTrees.getPath(e));
+            ClassSymbol enclosingClass = (ClassSymbol) scope.getEnclosingClass();
+            funcOp = attr.runWithAttributedMethod(scope.getEnv(), methodTree,
+                    attribBlock -> reflectMethods.getMethodBody(enclosingClass, methodTree, attribBlock, make));
+        } catch (RuntimeException ex) {  // ReflectMethods.UnsupportedASTException
+            // some other error occurred when attempting to attribute the method
+            // @@@ better report of error
+            ex.printStackTrace();
+            return Optional.empty();
+        }
+
+        // Reparse using API in java.base
+        try {
+            String opString = funcOp.toText();
+            Class<?> opParserClass = Class.forName("java.lang.reflect.code.parser.OpParser");
+            Method fromStringMethod = opParserClass.getDeclaredMethod("fromStringOfFuncOp", String.class);
+            return Optional.of(fromStringMethod.invoke(null, opString));
+        } catch (ReflectiveOperationException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
     /**
      * Returns the tree node and compilation unit corresponding to this
      * element, or null if they can't be found.
      */
     private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) {
