diff --git a/build.gradle b/build.gradle
index 8a3f88de7e..f3366a42e5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -254,6 +254,7 @@ allprojects {
 
     tasks.withType(JavaCompile) {
         options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-Xlint:-options" << "-parameters"
+        options.compilerArgs << '-XDenableSunApiLintControl'
         if (warnings_as_errors) {
             // We cannot fail the build on compiler warnings because we have java warnings that you cannot disable:
             // Signal is internal proprietary API and may be removed in a future release
diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt
index a3f329d101..12be389088 100644
--- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt
+++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt
@@ -36,16 +36,13 @@ data class NodeConfig(
         /** Pass-through for generating node.conf with external DB */
         val dataSourceProperties: Properties? = null,
         val database: Properties? = null,
+        val systemProperties: Map<String, Any?>,
         private val devMode: Boolean = true,
         private val detectPublicIp: Boolean = false,
         private val useTestClock: Boolean = true
 ) {
     companion object {
         val renderOptions: ConfigRenderOptions = ConfigRenderOptions.defaults().setOriginComments(false)
-        val systemProperties: Map<String, Any> = mapOf(
-                "net.corda.djvm" to true,
-                "co.paralleluniverse.fibers.verifyInstrumentation" to false
-        )
         val defaultUser = user("guest")
         const val CORDAPP_DIR_NAME = "cordapps"
     }
@@ -143,6 +140,7 @@ fun String.toKey() = filter { !it.isWhitespace() }.toLowerCase()
 
 fun <T> valueFor(any: T): ConfigValue = ConfigValueFactory.fromAnyRef(any)
 
+@Suppress("unused")
 private fun Config.withOptionalValue(path: String, obj: ConfigObject): Config {
-    return if (obj.isEmpty()) this else this.withValue(path, obj)
+    return if (obj.isEmpty()) this else withValue(path, obj)
 }
diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt
index 9b2b924c7c..c0fee9ad29 100644
--- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt
+++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt
@@ -1,6 +1,8 @@
 package net.corda.demobench.model
 
+import javafx.application.Application.Parameters
 import javafx.beans.binding.IntegerExpression
+import javafx.beans.property.SimpleBooleanProperty
 import net.corda.core.identity.CordaX500Name
 import net.corda.core.identity.Party
 import net.corda.core.internal.*
@@ -20,14 +22,37 @@ import java.time.Instant
 import java.util.*
 import java.util.concurrent.atomic.AtomicInteger
 import java.util.logging.Level
+import kotlin.math.max
 
-class NodeController(check: atRuntime = ::checkExists) : Controller() {
+class NodeController(
+    djvmEnabled: Boolean = readDJVMEnabled(),
+    check: atRuntime = ::checkExists
+) : Controller() {
     companion object {
         const val firstPort = 10000
         const val minPort = 1024
         const val maxPort = 65535
+
+        private const val MB = 1024 * 1024
+        const val maxMessageSize = 10 * MB
+        const val maxTransactionSize = 10 * MB
+
+        private fun readDJVMEnabled(): Boolean {
+            return FX.application.parameters?.let(::parseDJVMEnabled) ?: false
+        }
+
+        private fun parseDJVMEnabled(parameters: Parameters): Boolean {
+            val isEnabled = parameters.named["djvm"]
+            return if (isEnabled == null) {
+                parameters.unnamed.contains("--djvm")
+            } else {
+                java.lang.Boolean.parseBoolean(isEnabled)
+            }
+        }
     }
 
+    val djvmEnabled = SimpleBooleanProperty(djvmEnabled)
+
     private val jvm by inject<JVMConfig>()
     private val cordappController by inject<CordappController>()
     private val nodeInfoFilesCopier by inject<DemoBenchNodeInfoFilesCopier>()
@@ -77,7 +102,11 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
                 webAddress = nodeData.webPort.toLocalAddress(),
                 notary = notary,
                 h2port = nodeData.h2Port.value,
-                issuableCurrencies = nodeData.extraServices.filterIsInstance<CurrencyIssuer>().map { it.currency.toString() }
+                issuableCurrencies = nodeData.extraServices.filterIsInstance<CurrencyIssuer>().map { it.currency.toString() },
+                systemProperties = mapOf(
+                    "net.corda.djvm" to djvmEnabled.value,
+                    "co.paralleluniverse.fibers.verifyInstrumentation" to false
+                )
         )
 
         val wrapper = NodeConfigWrapper(baseDir, nodeConfig)
@@ -135,15 +164,14 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
         }
     }
 
-    @Suppress("MagicNumber") // initialising to max value
     private fun makeNetworkParametersCopier(config: NodeConfigWrapper): NetworkParametersCopier {
         val identity = getNotaryIdentity(config)
         val parametersCopier = NetworkParametersCopier(NetworkParameters(
                 minimumPlatformVersion = 1,
                 notaries = listOf(NotaryInfo(identity, config.nodeConfig.notary!!.validating)),
                 modifiedTime = Instant.now(),
-                maxMessageSize = 10485760,
-                maxTransactionSize = 10485760,
+                maxMessageSize = maxMessageSize,
+                maxTransactionSize = maxTransactionSize,
                 epoch = 1,
                 whitelistedContractImplementations = emptyMap()
         ))
@@ -203,7 +231,7 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
 
     private fun updatePort(config: NodeConfig) {
         val nextPort = 1 + arrayOf(config.p2pAddress.port, config.rpcSettings.address.port, config.webAddress.port, config.h2port).max() as Int
-        port.getAndUpdate { Math.max(nextPort, it) }
+        port.getAndUpdate { max(nextPort, it) }
     }
 
     private fun baseDirFor(time: Long): Path = jvm.dataHome.resolve(localFor(time))
diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeData.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeData.kt
index 15e57b1313..98dbce7c5b 100644
--- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeData.kt
+++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeData.kt
@@ -28,7 +28,7 @@ object SuggestedDetails {
     private var cursor = 0
 
     fun nextBank(exists: (String) -> Boolean): Pair<String, String> {
-        for (i in 0 until banks.size) {
+        for (i in banks.indices) {
             val bank = banks[cursor]
             if (!exists(bank.first)) {
                 return bank
diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/views/NodeTabView.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/views/NodeTabView.kt
index dd867fc1e0..99efed7c2f 100644
--- a/tools/demobench/src/main/kotlin/net/corda/demobench/views/NodeTabView.kt
+++ b/tools/demobench/src/main/kotlin/net/corda/demobench/views/NodeTabView.kt
@@ -150,6 +150,11 @@ class NodeTabView : Fragment() {
                             val toggle = radiobutton(notaryType.toString(), notaryTypeToggleGroup, notaryType)
                             toggle.isSelected = index == 0
                         }
+
+                        separator()
+                        checkbox("Deterministic Contract Verification", nodeController.djvmEnabled).apply {
+                            styleClass += "djvm"
+                        }
                     }
                 }
             }
diff --git a/tools/demobench/src/main/resources/net/corda/demobench/style.css b/tools/demobench/src/main/resources/net/corda/demobench/style.css
index 6b87beaa46..2900de0100 100644
--- a/tools/demobench/src/main/resources/net/corda/demobench/style.css
+++ b/tools/demobench/src/main/resources/net/corda/demobench/style.css
@@ -52,6 +52,10 @@
     -fx-spacing: 5px;
 }
 
+.services-panel .separator {
+    -fx-padding: 15px;
+}
+
 .cordapps-panel {
     -fx-pref-width: 600px;
     -fx-spacing: 5px;
diff --git a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt
index 818fe7d184..742bcfe543 100644
--- a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt
+++ b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt
@@ -41,12 +41,9 @@ class NodeConfigTest {
                 .withFallback(ConfigFactory.parseMap(mapOf("devMode" to true)))
                 .resolve()
         val fullConfig = nodeConfig.parseAsNodeConfiguration().value()
-        val systemProperties = nodeConfig.getConfig("systemProperties").toProperties()
 
         // No custom configuration is created by default.
         assertFailsWith<ConfigException.Missing> { nodeConfig.getConfig("custom") }
-        assertEquals(true.toString(), systemProperties.getProperty("net.corda.djvm"))
-        assertEquals(false.toString(), systemProperties.getProperty("co.paralleluniverse.fibers.verifyInstrumentation"))
 
         assertEquals(myLegalName, fullConfig.myLegalName)
         assertEquals(localPort(40002), fullConfig.rpcOptions.address)
@@ -133,6 +130,7 @@ class NodeConfigTest {
         assertEquals("cordacadevpass", webConfig.keyStorePassword)
     }
 
+    @Suppress("LongParameterList")
     private fun createConfig(
             legalName: CordaX500Name = CordaX500Name(organisation = "Unknown", locality = "Nowhere", country = "GB"),
             p2pPort: Int = -1,
@@ -142,7 +140,8 @@ class NodeConfigTest {
             h2port: Int = -1,
             notary: NotaryService?,
             users: List<User> = listOf(user("guest")),
-            issuableCurrencies: List<String> = emptyList()
+            issuableCurrencies: List<String> = emptyList(),
+            systemProperties: Map<String, Any?> = emptyMap()
     ): NodeConfig {
         return NodeConfig(
                 myLegalName = legalName,
@@ -155,7 +154,8 @@ class NodeConfigTest {
                 h2port = h2port,
                 notary = notary,
                 rpcUsers = users,
-                issuableCurrencies = issuableCurrencies
+                issuableCurrencies = issuableCurrencies,
+                systemProperties = systemProperties
         )
     }
 
diff --git a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt
index 46bbde3dfb..703c424a07 100644
--- a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt
+++ b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt
@@ -11,7 +11,7 @@ import kotlin.test.*
 class NodeControllerTest {
 
     private val baseDir: Path = Paths.get(".").toAbsolutePath()
-    private val controller = NodeController({ _, _ -> })
+    private val controller = NodeController(false) { _, _ -> }
     private val node1Name = "Organisation 1"
     private val organisation2Name = "Organisation 2"
 
@@ -63,6 +63,17 @@ class NodeControllerTest {
         assertTrue(controller.nameExists("organisation 1"))
     }
 
+    @Test
+    fun `test node system properties`() {
+        val data = NodeData()
+        data.legalName.value = node1Name
+
+        val wrapper = controller.validate(data) ?: fail("No wrapped configuration!")
+        val systemProperties = wrapper.nodeConfig.systemProperties
+        assertFalse(systemProperties["net.corda.djvm"] as Boolean)
+        assertFalse(systemProperties["co.paralleluniverse.fibers.verifyInstrumentation"] as Boolean)
+    }
+
     @Test
     fun `test register unique nodes`() {
         val config = createConfig(organisation = organisation2Name)
@@ -146,6 +157,7 @@ class NodeControllerTest {
         assertTrue(controller.keyExists("myname"))
     }
 
+    @Suppress("LongParameterList")
     private fun createConfig(
             organisation: String = "Unknown",
             p2pPort: Int = 0,
@@ -154,7 +166,8 @@ class NodeControllerTest {
             webPort: Int = 0,
             h2port: Int = 0,
             notary: NotaryService? = null,
-            users: List<User> = listOf(user("guest"))
+            users: List<User> = listOf(user("guest")),
+            systemProperties: Map<String, Any?> = emptyMap()
     ): NodeConfigWrapper {
         val nodeConfig = NodeConfig(
                 myLegalName = CordaX500Name(
@@ -170,7 +183,8 @@ class NodeControllerTest {
                 webAddress = localPort(webPort),
                 h2port = h2port,
                 notary = notary,
-                rpcUsers = users
+                rpcUsers = users,
+                systemProperties = systemProperties
         )
         return NodeConfigWrapper(baseDir, nodeConfig)
     }