diff --git a/modules/globals.js b/modules/globals.js
index a4ded6ec..d4422592 100644
--- a/modules/globals.js
+++ b/modules/globals.js
@@ -340,9 +340,14 @@ Object.defineProperty(this, "global", { value: this });
*/
/**
- * The `environment` object contains the Java system properties.
+ * The `environment` object contains the Java system properties and is specific to the Rhino engine.
+ * Java system properties are set on the command line using the `-Dproperty=value` syntax and
+ * can be modified during the runtime. They do not relate to the operating system's environment variables.
+ * Because of the misleading name of this global property, using [system.properties](../system#properties)
+ * is recommended.
* @name environment
* @see Java System Properties
+ * @deprecated Use the `system` module's `properties` and `env` exports instead.
*/
/**
diff --git a/modules/system.js b/modules/system.js
index 725065c2..ad39d9a0 100644
--- a/modules/system.js
+++ b/modules/system.js
@@ -95,10 +95,34 @@ exports.args = global.arguments || [];
* LOCALAPPDATA: 'C:\Local',
* ...
* }
- * @see java.lang.System.getenv()
+ * @see java.lang.System.getenv()
*/
exports.env = new ScriptableMap(System.getenv());
+/**
+ * @name properties
+ * Returns an unmodifiable view on the current Java system properties.
+ * @example {
+ * gopherProxySet: 'false',
+ * awt.toolkit: 'sun.lwawt.macosx.LWCToolkit',
+ * java.specification.version: '11',
+ * sun.cpu.isalist: '',
+ * sun.jnu.encoding: 'UTF-8',
+ * java.class.path: '/Users/nobody/ringojs/run.jar',
+ * java.vm.vendor: 'Eclipse Adoptium',
+ * sun.arch.data.model: '64',
+ * java.vendor.url: 'https://adoptium.net/',
+ * user.timezone: 'Europe/Vienna',
+ * ...
+ * }
+ * @see java.lang.System.getProperties()
+ */
+Object.defineProperty(exports, "properties", {
+ get: () => {
+ return new ScriptableMap(java.util.Collections.unmodifiableMap(System.getProperties()));
+ }
+});
+
/**
* Terminates the current process.
* @param {Number} status The exit status, defaults to 0.
diff --git a/src/org/ringojs/engine/RingoGlobal.java b/src/org/ringojs/engine/RingoGlobal.java
index a4378a34..9787c699 100644
--- a/src/org/ringojs/engine/RingoGlobal.java
+++ b/src/org/ringojs/engine/RingoGlobal.java
@@ -86,8 +86,10 @@ public void quit(Context cx, int exitCode) {
ScriptableObject.DONTENUM);
defineProperty("require", new Require(engine, this), DONTENUM);
defineProperty("arguments", cx.newArray(this, engine.getArguments()), DONTENUM);
+
// Set up "environment" in the global scope to provide access to the
- // System environment variables. http://github.com/ringo/ringojs/issues/#issue/88
+ // System environment variables. https://github.com/ringo/ringojs/issues/88
+ // DEPRECATED beginning with Ringo 4.x: https://github.com/ringo/ringojs/issues/456
Environment.defineClass(this);
Environment environment = new Environment(this);
defineProperty("environment", environment, ScriptableObject.DONTENUM);
diff --git a/test/all.js b/test/all.js
index 540858e1..54a5ce28 100644
--- a/test/all.js
+++ b/test/all.js
@@ -26,6 +26,7 @@ exports.testRepository = require('./repository/all');
exports.testIo = require('./io_test');
exports.testModules = require('./modules/all');
exports.testRhino = require("./rhino/all");
+exports.testSystem = require('./system_test');
// Also include integration tests.
exports.testIntegration = require('./integration-tests/all');
diff --git a/test/system_test.js b/test/system_test.js
new file mode 100644
index 00000000..0350529a
--- /dev/null
+++ b/test/system_test.js
@@ -0,0 +1,33 @@
+const system = require("system");
+const assert = require("assert");
+
+exports.testEnv = function() {
+ assert.throws(() => {
+ system.env.foo = "bar";
+ });
+ assert.throws(() => {
+ system.env.foo = {};
+ });
+}
+
+exports.testProperties = function() {
+ assert.throws(() => {
+ system.properties.foo = "bar";
+ });
+ assert.throws(() => {
+ system.properties.foo = {};
+ });
+
+ assert.isTrue(typeof system.properties["java.version"] === "string");
+
+ assert.isUndefined(system.properties["system.test"]);
+ java.lang.System.setProperty("system.test", "running");
+ assert.strictEqual(system.properties["system.test"], "running");
+ java.lang.System.clearProperty("system.test");
+ assert.isUndefined(system.properties["system.test"]);
+};
+
+if (require.main === module) {
+ system.exit(require("test").run.apply(null,
+ [exports].concat(system.args.slice(1))));
+}