GraalVM Polyglot API for embedding and executing Python code within Java applications.
—
Engine and language management provide comprehensive control over the GraalVM runtime environment, language discovery, and shared resources. The Engine serves as the foundation for multiple contexts while Language objects provide metadata and capabilities for installed language implementations.
Create and configure shared runtime engines for optimal performance and resource management.
/**
* Creates a new engine with default configuration
* @return new Engine instance
*/
public static Engine create();
/**
* Creates a builder for advanced engine configuration
* @return Engine.Builder for fluent configuration
*/
public static Builder newBuilder();
/**
* Gets the installed languages available in this engine
* @return Map of language ID to Language objects
*/
public Map<String, Language> getLanguages();
/**
* Gets the installed instruments available in this engine
* @return Map of instrument ID to Instrument objects
*/
public Map<String, Instrument> getInstruments();
/**
* Gets the engine version string
* @return version information
*/
public String getVersion();
/**
* Closes the engine and releases all resources
* Waits for any currently executing contexts to complete
*/
public void close();
/**
* Closes the engine with optional cancellation of executing contexts
* @param cancelIfExecuting if true, cancels any currently executing contexts
*/
public void close(boolean cancelIfExecuting);
/**
* Checks if the engine has been closed
* @return true if the engine is closed
*/
public boolean isClosed();Usage Examples:
// Simple engine creation
Engine engine = Engine.create();
// Check available languages
Map<String, Language> languages = engine.getLanguages();
if (languages.containsKey("python")) {
Language python = languages.get("python");
System.out.println("Python available: " + python.getName() + " v" + python.getVersion());
}
// List all available languages
System.out.println("Available languages:");
for (Map.Entry<String, Language> entry : languages.entrySet()) {
Language lang = entry.getValue();
System.out.println("- " + entry.getKey() + ": " + lang.getName() + " v" + lang.getVersion());
}
// Check instruments
Map<String, Instrument> instruments = engine.getInstruments();
System.out.println("Available instruments: " + instruments.keySet());
// Engine lifecycle management
try (Engine sharedEngine = Engine.create()) {
// Create multiple contexts sharing the same engine
try (Context context1 = Context.newBuilder("python").engine(sharedEngine).build();
Context context2 = Context.newBuilder("python").engine(sharedEngine).build()) {
// Both contexts share the same engine resources
context1.eval("python", "import sys; version1 = sys.version");
context2.eval("python", "import sys; version2 = sys.version");
// Contexts are isolated but share engine optimizations
context1.getBindings("python").putMember("shared_value", 42);
// context2 cannot see shared_value unless explicitly shared
}
} // Engine automatically closedConfigure engines with advanced options for performance, security, and debugging.
/**
* Builder class for creating configured Engine instances
*/
public static final class Engine.Builder {
/**
* Allows experimental options to be used (required for some advanced features)
* @param enabled true to allow experimental options
* @return this builder
*/
public Builder allowExperimentalOptions(boolean enabled);
/**
* Sets an engine option
* @param key option key
* @param value option value
* @return this builder
*/
public Builder option(String key, String value);
/**
* Sets multiple engine options
* @param options map of option key-value pairs
* @return this builder
*/
public Builder options(Map<String, String> options);
/**
* Sets the output stream for engine messages
* @param out OutputStream for engine output
* @return this builder
*/
public Builder out(OutputStream out);
/**
* Sets the error stream for engine error messages
* @param err OutputStream for engine errors
* @return this builder
*/
public Builder err(OutputStream err);
/**
* Sets the working directory for the engine
* @param workingDirectory path to working directory
* @return this builder
*/
public Builder currentWorkingDirectory(Path workingDirectory);
/**
* Builds the configured Engine
* @return new Engine instance
*/
public Engine build();
}Usage Examples:
// Advanced engine configuration
Engine configuredEngine = Engine.newBuilder()
.allowExperimentalOptions(true)
.option("engine.WarnInterpreterOnly", "false")
.option("compiler.CompilationThreshold", "1000")
.out(System.out)
.err(System.err)
.currentWorkingDirectory(Paths.get("/app/workspace"))
.build();
// Performance-oriented configuration
Map<String, String> performanceOptions = Map.of(
"engine.BackgroundCompilation", "true",
"engine.Compilation", "true",
"engine.CompileImmediately", "false",
"compiler.CompilationThreshold", "500"
);
Engine performanceEngine = Engine.newBuilder()
.allowExperimentalOptions(true)
.options(performanceOptions)
.build();
// Debug-oriented configuration
Engine debugEngine = Engine.newBuilder()
.allowExperimentalOptions(true)
.option("engine.TraceCompilation", "true")
.option("engine.PrintGraph", "Network")
.option("compiler.TraceTruffleCompilation", "true")
.build();
// Custom output streams for logging
ByteArrayOutputStream engineOut = new ByteArrayOutputStream();
ByteArrayOutputStream engineErr = new ByteArrayOutputStream();
Engine loggingEngine = Engine.newBuilder()
.out(engineOut)
.err(engineErr)
.build();
// Use engine and check output
try (Context ctx = Context.newBuilder("python").engine(loggingEngine).build()) {
ctx.eval("python", "print('Hello from Python')");
String output = engineOut.toString();
System.out.println("Captured output: " + output);
}Access detailed information about installed language implementations.
/**
* Represents an installed language implementation
*/
public final class Language {
/**
* Gets the unique language identifier
* @return language ID (e.g., "python", "js", "ruby")
*/
public String getId();
/**
* Gets the human-readable language name
* @return display name (e.g., "Python", "JavaScript", "Ruby")
*/
public String getName();
/**
* Gets the implementation name
* @return implementation name (e.g., "GraalPy", "GraalJS")
*/
public String getImplementationName();
/**
* Gets the language version
* @return version string (e.g., "3.11.0", "ES2022")
*/
public String getVersion();
/**
* Checks if the language supports interactive evaluation
* @return true if interactive mode is supported
*/
public boolean isInteractive();
/**
* Gets the language-specific options
* @return OptionDescriptors for this language
*/
public OptionDescriptors getOptions();
/**
* Gets the default MIME type for this language
* @return default MIME type (e.g., "text/x-python")
*/
public String getDefaultMimeType();
/**
* Gets all supported MIME types
* @return Set of supported MIME types
*/
public Set<String> getMimeTypes();
/**
* Gets the language website URL
* @return website URL, or null if not available
*/
public String getWebsite();
}Usage Examples:
Engine engine = Engine.create();
Map<String, Language> languages = engine.getLanguages();
// Detailed Python language inspection
Language python = languages.get("python");
if (python != null) {
System.out.println("Language ID: " + python.getId()); // python
System.out.println("Name: " + python.getName()); // Python
System.out.println("Implementation: " + python.getImplementationName()); // GraalPy
System.out.println("Version: " + python.getVersion()); // 3.11.0
System.out.println("Interactive: " + python.isInteractive()); // true
System.out.println("Default MIME: " + python.getDefaultMimeType()); // text/x-python
System.out.println("All MIME types: " + python.getMimeTypes());
System.out.println("Website: " + python.getWebsite());
// Check language options
OptionDescriptors options = python.getOptions();
System.out.println("Available options:");
for (OptionDescriptor option : options) {
System.out.println("- " + option.getName() + ": " + option.getHelp());
}
}
// Language capability detection
public class LanguageCapabilities {
public static void analyzeLanguage(Language lang) {
System.out.println("\nAnalyzing " + lang.getName() + ":");
// Basic info
System.out.println(" ID: " + lang.getId());
System.out.println(" Version: " + lang.getVersion());
System.out.println(" Implementation: " + lang.getImplementationName());
// Capabilities
System.out.println(" Interactive mode: " + (lang.isInteractive() ? "Yes" : "No"));
System.out.println(" MIME types: " + lang.getMimeTypes().size());
// Options count
OptionDescriptors options = lang.getOptions();
System.out.println(" Configuration options: " + options.iterator().spliterator().getExactSizeIfKnown());
}
}
// Analyze all available languages
for (Language lang : languages.values()) {
LanguageCapabilities.analyzeLanguage(lang);
}
// Find languages by capability
List<Language> interactiveLanguages = languages.values().stream()
.filter(Language::isInteractive)
.toList();
System.out.println("\nInteractive languages:");
interactiveLanguages.forEach(lang ->
System.out.println("- " + lang.getName() + " (" + lang.getId() + ")"));
// MIME type mapping
Map<String, Language> mimeToLanguage = new HashMap<>();
for (Language lang : languages.values()) {
for (String mimeType : lang.getMimeTypes()) {
mimeToLanguage.put(mimeType, lang);
}
}
// Use MIME type to determine language
String pythonScript = "print('Hello')";
String mimeType = "text/x-python";
Language detectedLang = mimeToLanguage.get(mimeType);
if (detectedLang != null) {
System.out.println("MIME type " + mimeType + " maps to " + detectedLang.getName());
}Use shared engines across multiple contexts for improved performance and resource efficiency.
/**
* Context.Builder methods for engine integration
*/
public static final class Context.Builder {
/**
* Uses the specified engine for this context
* @param engine the Engine to use
* @return this builder
*/
public Builder engine(Engine engine);
}Usage Examples:
// Shared engine for multiple contexts
Engine sharedEngine = Engine.newBuilder()
.allowExperimentalOptions(true)
.option("engine.BackgroundCompilation", "true")
.build();
// Create multiple contexts using the same engine
List<Context> contexts = new ArrayList<>();
try {
for (int i = 0; i < 5; i++) {
Context ctx = Context.newBuilder("python")
.engine(sharedEngine)
.build();
contexts.add(ctx);
}
// All contexts share engine optimizations and compiled code
for (int i = 0; i < contexts.size(); i++) {
Context ctx = contexts.get(i);
ctx.eval("python", String.format("""
def factorial(n):
return 1 if n <= 1 else n * factorial(n-1)
result_%d = factorial(10)
print(f"Context %d: {result_%d}")
""", i, i, i));
}
} finally {
// Close all contexts
for (Context ctx : contexts) {
ctx.close();
}
sharedEngine.close();
}
// Engine pooling for web applications
public class EnginePool {
private final Engine sharedEngine;
private final Semaphore contextLimiter;
public EnginePool(int maxConcurrentContexts) {
this.sharedEngine = Engine.newBuilder()
.allowExperimentalOptions(true)
.option("engine.BackgroundCompilation", "true")
.option("engine.CompilationStatistics", "true")
.build();
this.contextLimiter = new Semaphore(maxConcurrentContexts);
}
public <T> T executeScript(String script, Function<Context, T> operation) {
try {
contextLimiter.acquire();
try (Context context = Context.newBuilder("python").engine(sharedEngine).build()) {
return operation.apply(context);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} finally {
contextLimiter.release();
}
}
public void close() {
sharedEngine.close();
}
}
// Usage of engine pool
EnginePool enginePool = new EnginePool(10);
// Execute scripts using pooled engine
String result1 = enginePool.executeScript("2 + 2", ctx -> {
Value result = ctx.eval("python", "2 + 2");
return result.asString();
});
String result2 = enginePool.executeScript("'hello'.upper()", ctx -> {
Value result = ctx.eval("python", "'hello'.upper()");
return result.asString();
});
enginePool.close();Access and configure debugging and profiling instruments.
/**
* Represents an installed instrument for debugging/profiling
*/
public final class Instrument {
/**
* Gets the unique instrument identifier
* @return instrument ID
*/
public String getId();
/**
* Gets the human-readable instrument name
* @return display name
*/
public String getName();
/**
* Gets the instrument version
* @return version string
*/
public String getVersion();
/**
* Gets the instrument-specific options
* @return OptionDescriptors for this instrument
*/
public OptionDescriptors getOptions();
/**
* Looks up instrument services by type
* @param <T> service type
* @param type the service class
* @return service instance, or null if not available
*/
public <T> T lookup(Class<T> type);
}Usage Examples:
Engine engine = Engine.create();
Map<String, Instrument> instruments = engine.getInstruments();
// List available instruments
System.out.println("Available instruments:");
for (Map.Entry<String, Instrument> entry : instruments.entrySet()) {
Instrument instrument = entry.getValue();
System.out.println("- " + entry.getKey() + ": " + instrument.getName() + " v" + instrument.getVersion());
}
// Check for specific instruments
if (instruments.containsKey("profiler")) {
Instrument profiler = instruments.get("profiler");
System.out.println("Profiler available: " + profiler.getName());
// Get profiler options
OptionDescriptors profilerOptions = profiler.getOptions();
System.out.println("Profiler options:");
for (OptionDescriptor option : profilerOptions) {
System.out.println(" " + option.getName() + ": " + option.getHelp());
}
}
// Enable instruments with engine options
Engine instrumentedEngine = Engine.newBuilder()
.allowExperimentalOptions(true)
.option("profiler", "true")
.option("profiler.Output", "json")
.option("debugger", "true")
.build();
// Use instrumented engine
try (Context ctx = Context.newBuilder("python").engine(instrumentedEngine).build()) {
// Code execution will be profiled/debugged
ctx.eval("python", """
def complex_function():
total = 0
for i in range(1000):
total += i * i
return total
result = complex_function()
print(f"Result: {result}")
""");
}
instrumentedEngine.close();Monitor engine performance and resource usage.
/**
* Get performance statistics and metrics from the engine
*/
public class EngineMetrics {
public static void printEngineStats(Engine engine) {
System.out.println("Engine Information:");
System.out.println(" Version: " + engine.getVersion());
System.out.println(" Closed: " + engine.isClosed());
Map<String, Language> languages = engine.getLanguages();
System.out.println(" Languages: " + languages.size());
Map<String, Instrument> instruments = engine.getInstruments();
System.out.println(" Instruments: " + instruments.size());
}
}Usage Examples:
// Performance monitoring setup
Engine monitoredEngine = Engine.newBuilder()
.allowExperimentalOptions(true)
.option("engine.CompilationStatistics", "true")
.option("engine.TraceCompilation", "true")
.build();
// Monitor performance during execution
EngineMetrics.printEngineStats(monitoredEngine);
// Execute workload
try (Context ctx = Context.newBuilder("python").engine(monitoredEngine).build()) {
long startTime = System.currentTimeMillis();
// Execute Python code multiple times to trigger compilation
for (int i = 0; i < 100; i++) {
ctx.eval("python", """
def fibonacci(n):
return n if n <= 1 else fibonacci(n-1) + fibonacci(n-2)
fibonacci(20)
""");
}
long endTime = System.currentTimeMillis();
System.out.println("Execution time: " + (endTime - startTime) + "ms");
}
EngineMetrics.printEngineStats(monitoredEngine);
monitoredEngine.close();
// Resource usage monitoring
Runtime runtime = Runtime.getRuntime();
long memoryBefore = runtime.totalMemory() - runtime.freeMemory();
Engine resourceEngine = Engine.create();
try (Context ctx = Context.newBuilder("python").engine(resourceEngine).build()) {
// Heavy workload
ctx.eval("python", """
# Create large data structures
data = []
for i in range(100000):
data.append({'id': i, 'value': i * 2, 'description': f'Item {i}'})
# Process data
result = sum(item['value'] for item in data if item['id'] % 2 == 0)
print(f"Result: {result}")
""");
}
long memoryAfter = runtime.totalMemory() - runtime.freeMemory();
System.out.println("Memory usage: " + (memoryAfter - memoryBefore) / 1024 / 1024 + " MB");
resourceEngine.close();/**
* Descriptor for engine and language options
*/
public interface OptionDescriptor {
/**
* Gets the option name
* @return option name
*/
String getName();
/**
* Gets the option help text
* @return help description
*/
String getHelp();
/**
* Gets the option category
* @return category name
*/
OptionCategory getCategory();
/**
* Gets the option stability level
* @return stability level
*/
OptionStability getStability();
/**
* Checks if this is a deprecated option
* @return true if deprecated
*/
boolean isDeprecated();
/**
* Gets the option key for use in configuration
* @return OptionKey instance
*/
OptionKey<?> getKey();
}
/**
* Collection of option descriptors
*/
public interface OptionDescriptors extends Iterable<OptionDescriptor> {
/**
* Gets an option descriptor by name
* @param name the option name
* @return OptionDescriptor, or null if not found
*/
OptionDescriptor get(String name);
}
/**
* Option stability levels
*/
public enum OptionStability {
STABLE, // Stable public API
EXPERIMENTAL // Experimental feature
}
/**
* Option categories for organization
*/
public enum OptionCategory {
USER, // User-facing options
EXPERT, // Expert/advanced options
DEBUG // Debug/internal options
}Install with Tessl CLI
npx tessl i tessl/maven-org-graalvm-polyglot--python