Skip to content

Commit 3c2497a

Browse files
author
Elia Trachsel
committed
[GR-70659] Improving Ergonomics for EspressoLibs. This includes:
- automatically enabling EspressoLibs when there is no native access. - adding documentation about EspressoLibs.
1 parent ce73657 commit 3c2497a

File tree

6 files changed

+76
-9
lines changed

6 files changed

+76
-9
lines changed

espresso/docs/hacking.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,20 @@ $ mx espresso --java.JavaHome=/path/to/java/8/home -version
139139
$ mx espresso --java.JavaHome=/path/to/java/11/home -version
140140
```
141141

142+
## No-Native Espresso
143+
144+
To run Espresso without native access, use the experimental option `java.NativeBackend=no-native` via the command line:
145+
```bash
146+
$ mx espresso --experimental-options --java.NativeBackend=no-native
147+
```
148+
149+
or on the context builder:
150+
```java
151+
builder.allowExperimentalOptions(true).option("java.NativeBackend", "no-native")
152+
```
153+
154+
Disabling native access enhances security guarantees and sandboxing capabilities. In this mode, substitutions are used for Java's standard libraries, and virtualized memory will be provided (GR-70643). However, some functionality might be limited (e.g. you will have no access to LibAWT).
155+
142156
## Limitations
143157

144158
### Linux

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ private void initializeOptions(final TruffleLanguage.Env env) {
266266
case compact -> new CompactGuestFieldOffsetStrategy();
267267
case graal -> new GraalGuestFieldOffsetStrategy();
268268
};
269-
this.useEspressoLibs = env.getOptions().get(EspressoOptions.UseEspressoLibs);
270269
this.nativeBackendId = setNativeBackendId(env);
270+
this.useEspressoLibs = setUseEspressoLibs(env);
271271
assert guestFieldOffsetStrategy.name().equals(strategy.name());
272272
}
273273

@@ -355,6 +355,20 @@ private static String setNativeBackendId(final TruffleLanguage.Env env) {
355355
return nativeBackend;
356356
}
357357

358+
private boolean setUseEspressoLibs(final TruffleLanguage.Env env) {
359+
// For no-native we turn on espressoLibs by default
360+
boolean flagSet = env.getOptions().hasBeenSet(EspressoOptions.UseEspressoLibs);
361+
boolean userFlag = env.getOptions().get(EspressoOptions.UseEspressoLibs);
362+
if (nativeBackendId.equals(NoNativeAccess.Provider.ID)) {
363+
if (flagSet && !userFlag) {
364+
throw EspressoError.fatal("You should not set UseEspressoLibs to false with no-native backend!");
365+
}
366+
return true;
367+
} else {
368+
return userFlag;
369+
}
370+
}
371+
358372
@Override
359373
protected boolean patchContext(EspressoContext context, Env newEnv) {
360374
// This check has to be done manually as long as language uses exclusive context sharing

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,13 +620,16 @@ public Long apply(String size) {
620620
usageSyntax = "<argument>") //
621621
public static final OptionKey<OptionMap<String>> VMArguments = OptionKey.mapOf(String.class);
622622

623-
@Option(help = "Native backend used by Espresso, if not specified, Espresso will pick one depending on the environment.", //
623+
@Option(help = "Native backend used by Espresso, if not specified, Espresso will pick one depending on the environment.\\n" +
624+
"If native access is disabled, native methods will be emulated in Java with limited functionality.\\n" +
625+
"For example there will be no access to LibAWT.", //
624626
category = OptionCategory.EXPERT, //
625627
stability = OptionStability.EXPERIMENTAL, //
626628
usageSyntax = "<nativeBackend>") //
627629
public static final OptionKey<String> NativeBackend = new OptionKey<>("");
628630

629631
@Option(help = "Enable use of a custom Espresso implementation of boot libraries, which allows for not entering native code.\\n" +
632+
"Will be automatically enabled if there is NO native access.\\n" +
630633
"For example, this will replace the usual 'libjava'. Missing implementations will thus fail with 'UnsatifiedLinkError'.", //
631634
category = OptionCategory.EXPERT, //
632635
stability = OptionStability.EXPERIMENTAL, //

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ffi/EspressoLibsNativeAccess.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,25 @@
4545

4646
/**
4747
* Uses Espresso's implementation of standard JDK libraries, falling back to a delegate if the
48-
* implementation is missing.
49-
* <p>
50-
* This can be used in conjunction with option {@code 'java.GuestNativeAccess=no-native'} or
51-
* {@code env.isNativeAccessAllowed() == false} to prevent guest code from accessing the native
52-
* world, but still allowing the java standard library to work.
48+
* implementation is missing. Espresso Libs is automatically enabled if native access is disabled
49+
* (e.g., {@code java.GuestNativeAccess=no-native} or {@code env.isNativeAccessAllowed() == false}).
50+
*
51+
* Key implementation details:
52+
* <ul>
53+
* <li>Startup libraries (libnespresso, libjvm, libjimage) are substituted to prevent initialization
54+
* of native environments such as {@link com.oracle.truffle.espresso.jni.JniEnv} .</li>
55+
* <li>A custom guest FileSystem is backed by Truffle's VFS (see
56+
* sun.nio.fs.TruffleFileSystemProvider). The semantics of the FileSystem is implemented in
57+
* {@link com.oracle.truffle.espresso.io.TruffleIO} on the host side.</li>
58+
* <li>Network functionality is implemented using host sockets, relying on
59+
* {@code env.isSocketIOAllowed()
60+
* == true}.</li>
61+
* <li>Guest memory will be virtualized with (GR-70643).</li>
62+
* </ul>
5363
*
5464
* @see com.oracle.truffle.espresso.libs.Libs
65+
* @see com.oracle.truffle.espresso.io.TruffleIO
66+
* @see com.oracle.truffle.espresso.libs.LibsState
5567
*/
5668
public class EspressoLibsNativeAccess extends ContextAccessImpl implements NativeAccess {
5769

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/io/TruffleIO.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,25 @@
9090
import com.oracle.truffle.espresso.substitutions.JavaType;
9191

9292
/**
93-
* This class manages the set of file descriptors of a context. File descriptors are associated with
94-
* {@link String} paths and {@link Channel}s, their capabilities depending on the kind of channel.
93+
* Provides IO functionality in EspressoLibs mode (see
94+
* {@link com.oracle.truffle.espresso.ffi.EspressoLibsNativeAccess}). This requires managing the set
95+
* of file descriptors of a context.
96+
* <p>
97+
* This class plays a crucial role in EspressoLibs mode. Every guest channel gets associated with a
98+
* FileDescriptors which links to the corresponding host channel here {@link TruffleIO#files}. In
99+
* substitutions of native IO methods we receive the FileDescriptor as an argument which is then
100+
* used to retrieve the corresponding host channel. Then we can easily implement the semantics of
101+
* the guest channel's native methods using this host channel. For example see
102+
* {@link TruffleIO#readBytes(int, ByteBuffer)}.
103+
* <p>
104+
* For file IO the host channels is created over the Truffle API
105+
* {@link TruffleFile#newByteChannel(Set, FileAttribute[])} making this class practically a binding
106+
* layer between the guest file system (see sun.nio.fs.TruffleFileSystemProvider) and Truffle's
107+
* Virtual File System (see {@link org.graalvm.polyglot.io.FileSystem}).
108+
* <p>
109+
* For socket IO, file descriptors are associated with host network channels (see
110+
* {@link #openSocket(boolean, boolean, boolean, boolean)}).
111+
* <p>
95112
* Adapted from GraalPy's PosixResources.
96113
*/
97114
public final class TruffleIO implements ContextAccess {
@@ -166,6 +183,9 @@ public final class TruffleIO implements ContextAccess {
166183
* Context-local file-descriptor mappings.
167184
*/
168185
private final EspressoContext context;
186+
/**
187+
* The mapping between guest FileDescriptors and host channels.
188+
*/
169189
private final Map<Integer, ChannelWrapper> files;
170190

171191
// 0, 1 and 2 are reserved for standard streams.

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/LibsState.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
import com.oracle.truffle.espresso.vm.InterpreterToVM;
4747
import com.oracle.truffle.espresso.vm.Management;
4848

49+
/**
50+
* Class for maintaining state and providing utility in EspressoLibs mode. See
51+
* {@link com.oracle.truffle.espresso.ffi.EspressoLibsNativeAccess}
52+
*/
4953
public class LibsState {
5054
private static final TruffleLogger logger = TruffleLogger.getLogger(EspressoLanguage.ID, LibsState.class);
5155

0 commit comments

Comments
 (0)