Seeking review and comments on R/W tags

John Crowley jdcrowley at gmail.com
Fri Jun 16 12:42:52 UTC 2017


Martjin,

You are correct - this is not a security environment and can be "broken" by reflection or bytecode fiddling - in much the same way that reflection allows someone to reference a private variable. 

Can also be broken by tagging a method with F (forced read-only) and then mutating something - but at least here the compiler would issue a warning that the rules were violated. And a JNI native method tagged with an F is completely opaque to the compiler and can mangle anything.

Also understand your reluctance to introduce more syntax into the language. 

The use of annotations was considered, but finally decided on the existing tags for the following reasons:

All tags default to W and are optional - so existing Java source code, with no tags at all, will compile and execute the same as before,

The R/W information has to be pervasive, so annotations would start to get very clumsy - e.g. 
@tags(:RR,myArray[:RR][:RW][:WW]) 
public Date myArray[][][] = …

		vs  public Date:RR myArray[:RR][:RW][] = …

IMHO the annotation approach requires some mental effort by the reader to match up the tags to the declaration. It would also be very easy for the developer to accidentally mis-match the R/W tags and the ultimate variable declaration (especially a maintenance developer less familiar with the original code). Consider the annotation that would be required for the example from the paper - Map:RW<Date:P, List:RW<Message:RW>>

Saving the R/W tags into the compiled class file by using the existing Signature entry seemed like the least invasive change, and again makes it obvious to anyone who runs javap to see the generated code.


Thanks for your comments. The point of submitting this to valhalla was precisely to have some other (and more expert) eyes take a look!

PS: The initial version of a presentation is now also on the shared drive - https://drive.google.com/open?id=0B9h3YMINZ271dWcyS1RjbEZLMHc <https://drive.google.com/open?id=0B9h3YMINZ271dWcyS1RjbEZLMHc>   Hope that it is somewhat understandable without a narration, but still WIP.

Thanks,

John Crowley
Westport, CT
203-856-2396




> On Jun 15, 2017, at 3:38 PM, Martijn Verburg <martijnverburg at gmail.com> wrote:
> 
> Hi John,
> 
> Looks like some interesting research!  I'll confess I haven't got the JVM knowledge to comment in depth apart from my earlier observations that this will need to be a patch against Java 10+ in order to be reviewed at the code level.
> 
> I'm assuming that use of reflection or runtime bytecode modification could still 'break' the predicates here and I'd have a preference of not introducing further syntax to the Java developer (i.e.  If a way could be found to do a majority of this via annotations then I think it would cause less friction).
> 
> Please note I Am Not A JVM Expert (IANAJE), so take my comments with a large dose of salt.
> 
> 
> 
> Cheers,
> Martijn
> 
> On 16 May 2017 at 18:18, John Crowley <jdcrowley at gmail.com <mailto:jdcrowley at gmail.com>> wrote:
> Hi All,
> 
> I’m looking for some help to review a proposal.
> 
> For a while now I’ve been working toward the goal of providing declarative immutability in Java - by having Read/Write tags on variables, references, methods, and generics. (Similar, but more extensive, than the const keyword in some languages.)
> 
> Things have progressed to the point that a few more (expert) eyes would be appreciated to review and comment on whether this is feasible and desirable.
> 
> A short summary follows, but everything is available here - https://drive.google.com/open?id=0B9h3YMINZ271dWcyS1RjbEZLMHc <https://drive.google.com/open?id=0B9h3YMINZ271dWcyS1RjbEZLMHc>
> 
> A document with a complete description,
> A modified (Java 8) compiler which implements the initial portion of the concept (the Report Card lists what is supported).
> A README file which describes where everything is on this drive.
> 
> A very condensed description ….
> 
> The Problem
> Variables can be protected by making them private and using getters/setters to control access - but at the cost of complexity, additional code, and runtime overhead. 
> 
> Object instances are a more severe problem - once anyone has a reference, they can modify any visible variable, and call mutating methods. 
> 
> When calling a method on an instance, the caller does not know if that method mutates that instance (or some referenced instance).
> 
> The Proposal
> A set of single-character tags is proposed - W = writable, R = read-only - that can be appended to variable definitions, types (references), methods, and generics (more below).
> 
> Variable declarations may have 2 tags - the first controls outsiders and the second the owner. (The owner is defined as the innermost context which declares the variable.) For example,
> 
> 		public Date lastActivity:RW = new Date()
> 
> specifies that the owner (the declaring class) may assign a new Date instance to lastActivity, but no outsider may. Even stronger,
> 
> 		public Date lastActivity:RR = new Date()
> 
> specifies that neither an outsider nor the owner may change the Date instance referenced by lastActivity (equivalent to the final keyword).
> 
> The remaining problem is that anyone can change the semantic value by lastActivity.setTime(….). This can be controlled by tags on the type specification:
> 
> 		public Date:RW lastActivity:RR = new Date()
> 
> where the Date:R portion specifies that an outsider cannot modify any visible variable in the target instance and can invoke only read-only methods (myMethod:R).
> 
> The owner may update the instance - presumably to update the timestamp of the last activity processed. (The owner of an instance is the context which instantiates that instance.)
> 
> This is a strong API definition - outsiders know that they may create and retain a local reference and it will always refer to the same instance, and the owner has been able to make the information public with the assurance that no one else can tamper. 
> 
> (Note that if the variable were private with a getter, then all outsiders would have to invoke a method, and to be safe the owner must return a cloned instance.)
> 
> Methods and their parameters may also be tagged. myMethod:R specifies that myMethod does not modify the instance (or any internally referenced instance) - and this is validated by the compiler. myMethod(Date:R myParameter, …) considers the passed Date instance as read-only within the method. If the method is tagged as R, then all parameters must also be tagged as R (the compiler infers this for untagged parameters, an explicit W tag is an error).
> 
> Extending these tags to generics allows control at all levels of the declaration. Assume that a class Message… exists, then
>  
> 		List:RW<Message:RW>
> 
> specifies that outsiders may not modify the List (add/delete elements) nor mutate any Message within the list. The owner may do both - e.g. add new Messages to the List, update a Message when it is acknowledged, etc.
> 
> A final tag of P (= Pure) may also be attached to a type declaration - Date:P - and ensures that no mutable reference exists to this instance - it will be immutable throughout the application. Important information for any developer, and allows the compiler to utilize all possible optimizations.
> 
> As a last example, consider:
> 
> 		public Map:RW<Date:P, List:RW<Message:RW>> history:RR = new Map<Date, List<Message>>
> 
> which is a (live) history of all of the Messages processed on a given day (assumption: the HH:MM:SS.sss portion of the Date is zeroed).
> 
> This tells any user that the Map is live, the key (Date) is Pure (good for the key of a Map), and the List and Messages will be updated as events occur. The history variable will always reference the same Map. The compiler will flag any attempt by an outsider to modify anything at any level, and will also flag an attempt by the owner to use a Date key which is not immutable. (In a multi-threaded environment, synchronized versions of Map, List, and Message would be necessary.)
> 
> Status
> The modified compiler enforces most of the above at compile time - so it appears that implementation is feasible.
> 
> Key questions remain where review by outside experts is needed:
> Is the syntax complete? Unambiguous?
> Are the semantics complete? Are there reasonable coding paths which lead to contradictions? Is there any path where a readonly tag can be converted to a mutable tag?
> Is this useful to the developer? Does it produce more robust code? Better APIs? Fewer LOC? Better runtime performance?
> 
> Thanks for your help,
> 
> John Crowley
> Westport, CT
> 203-856-2396
> 
> 
> 
> 
> 



More information about the valhalla-dev mailing list