 So hello My name is Christoph Langer. So I'm the second in the row of three guys from SAP speaking here So the one or the other might know me from the open JDK community So you might see me on the mailing list. I try to to support Andrew in maintaining the JDK 11 updates release I think that's most of the work which takes most of my time What I'm doing an open JDK at the moment. So it's doing a lot of testing integration and so on But today I actually have the pleasure to talk about the work of my colleagues Namely, you got slim Maya who will more or less did all the Progress to bring this into open JDK, but he decided to go surfing in South Africa Usually is here, but this year. So the turn is on me Okay, so as it's Already a bit late. So the brains have been wrenched a little bit over the day It's maybe not the Mostly most sophisticated topic of the day or at least not from from how it looks like because I mean a little night pointer exception It's not too complicated. Just the sentence that everybody can understand But okay, and there's some some logic behind it, which is yeah, which is really quite some some algorithm Let's say so and yeah, we come to that later So yeah, what I'm gonna cover I start with how helpful are the night pointer exceptions currently? How helpful could they be so Taking them an example as motivation Talked about what we did what we brought to the open JDK where we are there and then it's for stem So we talk technical and try to explain the algorithm behind it a little bit and in the end there are a few things Which still Can be done and could maybe leverage this so yeah, I come to that in the end Okay, yeah, how helpful are night pointer exceptions? So imagine this little code snippet, so I cut and pasted it out of some source code line 33 we see some object with fields and There's another field has some payload there's an assignment to this payload field from another Chain of object fields. So what would we get currently we get something saying exception and threat main night pointer exception? Okay, we see the the fine name and the line like line 33 but wouldn't it be nice if we Knew what what exactly what's the field that's now here? Yeah, okay, so Yeah, could be like this. Oh So the test cannot read field D because a 2 dot B dot C is now so we know okay. It was exactly this this guy here Okay, yeah, obviously night point exception could look like this and yeah so this is what we contributed to the open JDK actually the The thing behind it was already implemented years ago by colleagues for our commercial Edition of the JDK it's quite sub JVM But only the SAP customers using SAP products with based on Java could benefit of it But you are quite sure that that it works at least and so last year Out shortly after first time I think that the initial mail gets proposed it on the mailing list Just said okay, it's a little enhancement cannot be that thing Yeah, and this proposal was welcomed by people obviously by the developers of Java and People saying yeah sure about time to have it in but it was challenged to because out of several reasons So so one thing is always okay You don't maybe want to have too much information in exception messages because you don't want to leak too much data To maybe some attacker or so who can then read something so maybe that's a concern then one thing is performance So we want to one don't have negative performance impact by such Computation of messages here and then it was also about the approach So we did this really in the hotspot VM coding and C++ So people stepped up and said hey, can we have a look maybe we can do it in Java with with No bytecode APIs and stack walking APIs, etc. Well, yeah, okay that was part of the discussion and I don't know it evolved then people from Oracle came up and I think they motivated guts to to make it a jab And with the help from I think Colleen Alex Buckley and so on so we brought it to to a point Where it was admitted to JDK 14 and we could push this to write a time for JDK 14 in October last year So yeah, it's available But it's not the default. So you have to use this This flag to activate it otherwise you will see is it still see the the old scars message But yeah, you can you can switch it on and before for the sub machine binary distribution We switched it on by default as we are confident in it and we also back ported it to a submachine 11 edition So if you want to try with JDK 11 and use submachine and you don't need an additional flag But I guess I don't know we can also discuss about back porting it to open JDK 11 if there's interest okay, so Yeah, some technical insights The nine pointer exception message You see the green line. It says cannot read field D because a to dot B dot C is now It has two parts. So the first part is what meant wrong cannot read field D And the second part that's a more complicated part I'd say you have to go back and the program flow a bit to figure out What exactly was the reason what brought the Nile point and the Nile reference on to the the operand stack And it's also important at the time we we can create a message We have we have a bytecode index of where we are at the method While we we are as we are not spot we am we can query for the bytecode for the constant pool But we have we don't have the the program data at that moment We have no variable constants or things like that. So we have to live with with what we have here Okay, so Then okay, let's take some simple example So really an easy thing you initialize an object with Nile and invoke the method to string on it on this Nile reference So you will get a nine pointer exception So this in bytecode Will will work like this so at first you have the acorns Nile instruction this pushes the Nile reference on the operand stack So basically Java bytecodes, you know, maybe people are not so familiar with it it works like The instructions they push and pop things on an operand stack and it's defined for each bytecode What it's expected before on the operand stack and how it would it look like in the end what arguments are popped and what's pushed there So okay, so to do an object initialization. You will obviously at first then load the the Nile You initialize the Local variable slot the slot one with the A star one instruction that pops the Nile reference from the operand stack and it's stored in this lot Okay, that was the first line of the example then the second line does a load one and it loads again from this slot of the variable pushes the value on the stack So yeah, we had it initialized with now So there will be a Nile on the stack and then we try to invoke the two string methods with invoke virtual instruction Yeah, afterwards the the the reference will be gone But in our case we get an eye pointer exception because it was Nile the method we tried to invoke the Object we tried to invoke the method on Okay, and now from the failing bytecodes we can we can generate this text message about the failed operation For the course we have to walk back as I said And so that's what the what the this algorithm starts with is really to to replay all this From the from the entry to the method until the point where the Nile pointer exception happened And that we have for each bytecode we have representation of this operand stack and then from this operand stack We have backlinks for each field to the instruction which pushed the value there and so then that helps us to to then Walk and then generate the message Okay, so part a what bytecode fails not every bytecode Can can cause a Nile pointer exception So we have here the the array operations or if the array you want to access Is Nile and you can say something that I cannot load from into ray for instance element type So the array length cannot read the array length Forget field and put field instruction. I cannot read. I cannot assign a field Ideally we also have the field name from the constant pool here Those invoke instructions like we saw here they then what the message would be cannot invoke a method Throwing exceptions and and entering and exiting monitors. They also need objects so, yeah, that's the simple switch statement on This bytecode like here they more virtual and we come to this part a of the message Okay, then for the for the for the second part the be cause why the my point exception was pushed There's a little bit more to be done here. Okay in the easy case. You have something like a const null Okay, then we can only say null is now sure There are constant operations so we can we know the constant that is pushed on the stick we can just name it so for an array We do two things so at first we go back the path from for the bytecode that pushed the array reference So this could also come from another field Like in the example I had like several field references So we really have to go recursively back until the point where where we started at Okay, then and then with the brackets and then we also write something about who put the index there Yeah Okay, so get field get field we can write the field name, but then we have to get also the cause for the for the reference that the get field was invoked Get static there we have class name and field name. That's the easy thing. So those Invoke instructions So that's when when methods are called then we can say okay the return value of the method is or In some places we would only give method names like in in the index computations of the array accesses And then the load instructions for for loading and storing variables Okay, so in our case it was an a load which put the now reference on the stack and they load comes from there from the Variable object and so then we can say okay Cannot evoke object because check isn't I okay, so Yeah, there's some more things I want to mention here about this so one thing is This calculation of the message is only done when we invoke the get message method of an exception so at the time the VM generates such an exception it really just stores the bytecode the stack information as it did before and so no change about that and Only when somebody it calls like print stack trace or so it will call get message and then we we would do all this So an unusual flow of Java VM You should not see an impact because I mean exceptions get thrown get caught and not necessarily Printed out messages Yeah I can and the first thing was it's also we're talking only about the messages Generated by the VM itself. So there's also possible like I can do a new nile pointer exception Construct an exception, but here. Yeah, then the developer knows what he's doing He would probably also enter a meaningful message already. So, okay, we won't capture this Then there's something like hidden frames for instance when you have lambdas and then there are some frames put in by Java C and the VM So those stack frames are taken so if we hit an eye pointer exception there Then we would not generate the message because it's probably not so meaningful to two people looking at the exception then the point it's implemented in in the virtual machine and the C++ code Why did we do that? Yeah, the thing is we have really everything at hand I mean we are in the VM we can query for the bytecodes for the constant for everything and on the Java side Okay, there's a stack walker and they're also bytecode APIs, but it's more complicated to to get all the data we'd need here So I think it was really the the best way And in the end I come to that and you know we come in the end to that maybe by this Algorithm or this this part this bytecode class we can leverage it for other exceptions as well, so Okay, then another point The best results you will see obviously when you compile the Java class With the with the right debug settings. So a default of Java C It's only the lines and source information, so in the code text you will get the line numbers and the source file But you usually don't have the variables unless you compile with this minus G flag or this minus G Was line source whatever you can specify so once we have the variables Then we can we can print them in the message if you don't have them for for locals We have to print something like parameter one parameter two for the for the method or for local variables It's even more complicated because then we only have slot numbers and so it's not really Accurate or if you don't know what the compiler does where the variables get allocated Yeah, okay So Yeah, I think still to be done. So as I said this feature is now kind of beta. It's it's disabled So we are hoping to to get to this enabled by default one day. So Maybe let's see how the the feedback is but we will try to to ask The the open JDK community if we can switch it on Then there's something objects require non-null so You might heard about that one. So this is some place Maybe also means of tackling such nine-pointed exceptions. You can before you you call into another method You can wrap it with a call to objects require non-null Then at that place before we actually enter the method we check for the Nile Then you have a defined place in the code where this could happen Also, you would not go further down the program and see the nine-point exception at places where you where you really don't want it But on the other hand, then you lose this information because this is then a nine-point exception that the developer has Written or has constructed. So, yeah, our thing is not applied then Okay then There's a thing like single file source code mode. So there was JAP 330 you can now you don't need to use a Java file Compile it and and and work Java with the class file, but you can go like in script mode or so called Java the Java file and then The you at the moment also don't have this Those nine-pointed exceptions would also be nice to have it here and what you can do is you can set the VM option Yeah By parameters to the Java, but you can't modify the compiler at the moment You can't set the minus G option to have the variable. So that's something where we have to find a solution Then okay the Jshare use case I mean, that's really something where you want to go and just prototype something and Jshare And then it would also be nice to really get those nine-pointed exceptions here So if we do the ballot one and enable it as default then Jshare will have it Otherwise, at least maybe we can make it a default for the Jshare And then there's another place where the algorithm might be applied It's the array index out of bounds exception. I think we have some time left. So I can try to demo it Then I've prepared a little prototype. I actually was good So Yeah, so you see here, it's a test case where we do out of bounds accesses on arrays Okay, so Maybe go even back to a Java 8 time. So if I run it with JDK 11, so you see here It only tells you the index array index out of bond exception index 5 in line 12 So now, okay, it's only one one array, but if you have a chain of arrays Maybe like here array one two minus one So, okay, as we have here the minus one only in one place we can guess it must must have been this array access Okay, then there's a little enhancement already part of I know was it 10 or 11 which was contributed by by Goods Was it more helpful, right? So you can we can see the index out of bounds for the length So the array had only the length for it already helps a little bit more And now if you use the the same algorithm as in the nine-pointer exception We'd go and This is even more helpful So we can really come to some statement about What index was it and the rain name? Yeah, so That could leverage the feature too. So, yeah Okay, I think I'm at the end So if you have questions Happy to answer Hey So one use case for which I think it's important to have better No pointer messages with respect to the objects required on all is wherever Basically, there are places where they have a C compiler. We insert those checks I know at least two places one is string is strings and switch and the second is when you construct an inner class from From an enclosing class instance in these cases you can get a no pointer exception but We won't get any benefit from this work because it's just An opaque call to require them now. Yeah, so for that actually, I mean I also got also did a prototype I brought it here. So maybe we can Can demonstrate it too? So that's that's this class It's okay. I mean, it's really a constructed This presentation mode doesn't jump over Yeah, I know that's what I'm trying to fix Maybe try this duplicate Yeah, okay. So, yeah, this is the This example here. Okay, it's a bit constructed. I mean you have a chain of require nonetheless here But here it would have Because with the with the current thing What is this the standard thing? So again, I get only a nine pointer exception And yeah, I know it's like require no null and in require no null and it comes from my line 23 in main Which is this one? Oh, but which require no null was it? and if we Yeah, we prototype using the that point exception algorithm here and So, yeah Here we get some message like okay They were still occurs and require no null But as we know this is this method we can jump back the stack and then do this computation of the bytecode here and come to Come to some explaining message. So that was just an initial approach So I think it's about time that we can discuss it on a mailing list to refine it I have a question You said you need to to compile it with line information with what we find information What would the message look like if the while information is not compiled with? Yeah, I think I also have something here Where can like local param? Okay, yeah, okay, so here we have a we have a function called with a method parameter and also we have a local So I have to tell eclipse to change the compilation Java compiler take this knob Okay, and then we can run it with What is the NP-01 I always have problem local param here Okay. Yeah, you see it. So it would tell you parameter one so This is okay, and then you have here local local to I think yeah And but local to is is the the slot number because here in the I think the slot zero is the this pointer to the object one is used for the parameter index and then the slot two is Local index so yeah, maybe we should rather say something like a local slot or so that for for people analyzing this it's clear It's not necessarily the the local variable number two because he's only one But it's maps rather to the slot number No But I mean there's more information than before Okay one question You have the information of the very variable Is there a way to get the class information? Which class is involved? Yeah, I think we we use it here So in this example like this so But the class information that's easy there You don't need to have the compilers variable information because the classes with their fields and their names That's part of the constant pool at runtime. So That's easy. I was just wondering and this would be a bit It's a set water damage if something Bike code transformed a method and injected code into it. Have you looked at what would happen if that was done? I'm not just think I'm something like bite man where I could I could probably break this very quickly And it would be very rude of me to do so But I was thinking where you've got code transformers like middleware that does changes to code How much would that make this less meaningful or do you know? Actually, I don't know how much got tested those cases. I mean there are also things like it's not about Java It's also like other languages or so which compile it down to bytecode So I would think it's it's still kind of useful to see more information at least like before but Yeah, it's something to be evaluated. Probably probably yeah So you you answered half of the question I was going to ask by showing the requires null thing Why wouldn't we want to do that in all cases if if a null was passed in as an argument Walk back up until we get to a field load somewhere and say it came from this call further up the stack And that's where that null actually boiled out and came into this method because right now I think normally it's just local the details are just local to the method, right? Yeah Yeah, maybe in the case where where there's no custom message which we don't want to override now Maybe we can think about that Or maybe we can use an annotation or something where you want to see it But then you have to annotate methods so there was Brought up in the discussion for this object's require non-null support that that would be one way to tackle it Would it be able to tell me that the parameter or the local is an int in this case again The local is it yeah That the type of the variable if I have like a bajillion locals But each one has like this super long class name I think yes, you have access to the signature of the method So that should be possible gets more complicated with the stack slots again because then you have white slots or Just one slot it depends so then then it's really it's a problem, but for the method signature it should be there Good question on the status. So you mentioned that You had a CB machine you have this in version 11 Yeah, I know that red hat being a steward of 11 you doesn't necessarily object to new features like Shenando being backboarded Now I wonder if this is the one of those jobs that could be backboard to 11 users Yeah, I mean, I mean have you discussed this or is this Discuss this window so we didn't bring it up to the table yet. I mean, we were just happy in October that okay Finally, it's in let's settle it a bit, but okay. Yeah, we can start Because this this does change things Existing application may not as bad those exceptions isn't it yeah Maybe it's over if you bring it to 11 it would be good idea also to keep it under the flag and don't enable it by default Time's up So I implemented this in Android five years ago or it became public five years ago But not to the extent that you've done it here And the biggest pain in getting this enabled was people who had unit tasks where they would capture the exception Put it into a file And then all of these golden file tests all broke. Yes And you keep mentioning changing the message and things like that and I just keep imagining all of these units has breaking and breaking again Yeah, I mean even for the SAP machine when we when we enabled it We had to go and I mean we are running JT REC test regularly and some things So we had to change a few places where the golden file had the simple nine point exception Okay, so I think time's up So