<div dir="ltr">Hi Ron,<br><br>I’ve read this draft a number of times and each time I struggled with the framing of the problem given Java’s success over the past almost 30 years.<br><br>Framing the problem with statements like: <br>      “Strong encapsulation offers a solid foundation to build on. <br>      Without it, code is a castle in the sand.” <br><br>sets the conversation off in the wrong direction.  I started to respond in terms of these kinds of statements and found the response wouldn’t have been helpful to move the conversation forward.<br><br>Instead, I stepped back and looked at the larger context.  In particular, I’m reading this in light of JEP 411: Deprecate the Security Manager for Removal [0] and the eventual goal of completely removing the SecurityManager.<br><br>Let me lay out how I see this and you can correct me where I’ve gone off the rails.<br><br>As JEP 411 states, the SecurityManager has:<br>* Brittle permission model<br>* Difficult programming model <br>* Poor performance<br>Which translates into a whole lot of cost both for maintainers of the JDK and for all users who must pay the runtime costs related to the SecurityManager (high when enabled, but non-zero always).<br><br>Although the SecurityManager has high costs, and is infrequently used at runtime in production, it provides the only way to limit certain capabilities like:<br>* JNI (SecurityManager::checkLink)<br>* Encapsulation (SecurityManager::checkPackageAccess)<br>* Launch new processes (SecurityManager::checkExec)<br>* Reflective access (accessDeclaredMembers, etc)<br>* and others<br><br>Some of those controls need replacements if the SecurityManager will go away.  JNI, surprisingly, is a key one here for large corporations.<br><br>If I understand correctly, this new Integrity JEP draft aims, amongst other things, to replace the hard to maintain, expensive runtime checks of the SecurityManager with configuration via command line options.  This allows those who previously relied on the SecurityManager to continue to control the high-order bits of functionality without imposing a cost on the rest of the ecosystem.  It also makes it easier to determine which libraries are relying on the restricted features. <br><br>Overall, this provides a smoother migration path for users, makes the intention of users very clear (just read the command line vs auditing SecurityManager implementation) and improves performance by shifting these decisions to configuration time rather than paying cost of code complexity and stack walks.<br><br>I also appreciate the “nudge” being made with this JEP by requiring explicit opt-in to disabling protections versus the previous uphill battle to enable the SecurityManager.  It makes for an easier conversation to ask for i.e. JNI to be enabled for one library on the command line rather than having to deal with all the potential restrictions of the SecurityManager.<br><br>So while overall, when viewed from the lens of removing the SecurityManager, this approach makes sense, I do want to caution on betting against Java’s strengths, particularly against its use of speculative optimizations.<br><br>> Neither a person reading the code nor the platform itself – as it compiles and runs it – can fully be assured that the code does what it says or that its meaning does not change over time as the program runs.<br>…..<br>> In the Java runtime, certain optimizations assume that conditions that hold at the time the optimization is made hold forever.<br><br>This is the basis of all speculative optimization - the platform assumes the meaning doesn’t change and compiles as though it won’t.  If the application is modified at runtime, the JVM applies the necessary compensations such as deoptimization and recompilation.<br><br>Java has bet on dynamic features time and again (even when others have championed static approaches) and those bets - backed by speculative optimizations - have paid off time and again.  So this can’t be what you’re arguing against.<br><br>If the concern is that the runtime behaviour may appear to be different than the intent expressed in the source code due to use of setAccessible or changes by agents, then I think the JEP should be more explicit about that concern.  The current wording reads as equally applying to many of Java’s existing dynamic behaviours (and belies the power of speculation coupled with deoptimization!).<br><br>And a few smaller quibbles:<br><br>> For example, every developer assumes that changing the signature of a private method, or removing a private field, does not impact the class's clients.<br><br>Right.  The private modifier defines a *contract* which states anyone depending on the implementation details are on their own and shouldn’t be surprised by changes.  I understand that it can be problematic when large successful frameworks are broken by such changes, but that doesn’t invalidate the contract that’s in place.  The risk is higher for the JDK than for other libraries or applications given the common dependency on the JDK.<br><br>> However, with deep reflection, doSensitiveOperation could be invoked from anywhere without an isAuthorized check, nullifying the intended restriction; even worse, an agent could modify the code of the isAuthorized method to always return true.<br><br>And clearly, these would be bugs.  Not much different than leaking a privileged MethodHandles.Lookup object outside a Class’s nest (the boundary for private access) for which there is no enhanced integrity check.<br><br>We can’t fully protect users from code that does the wrong thing even while undertaking efforts to minimize the attack surface.  “Superpowers” are exactly that, while we support making them opt-in, we should be careful not to overstate the risk as the same principle applies to all code running in a process - it must be trusted as it has the same privileges as the process.<br><br>> A tool like jlink could remove unused strongly-encapsulated methods at link time to reduce image size and class loading time. <br><br>Most of the benefit here is not time saved by not loading the methods, it’s actually due to avoiding the need to load classes during verification.  The verifier needs to validate relationships between classes and every extra method potentially asserts new relationships (such as class X subclasses Throwable) and it is these extra classes that need loading that typically increases the startup time.<br><br>> The guarantee that code may not change over time even opens the door to ahead-of-time compilation (AOT).<br><br>AOT doesn’t depend on the code never changing.  OpenJ9 has AOT code that is resilient in the face of changes to the underlying Java class files.  I’m positive Hotspot will be able to develop similar resilient AOT code.  The cost of validating the assumptions made while AOT compiling is much lower than doing the compile while still enabling Java’s dynamic features.<br><br>–Dan<br><br>[0] <a href="https://openjdk.org/jeps/411">https://openjdk.org/jeps/411</a><br></div>