[MUSIC PLAYING]
ELLIOT HUGHES: Hi, my name's Elliot Hughes.
I've worked on Android for a while now,
and actually, my first job on Android
was working on the Java core libraries
and actually cleaning up some of the bugs in our JNI.
So first off, I'll show you what you're probably
expecting to see when you think JNI, which is code that looks
like this, and I'm guessing no one can
tell that the code that actually does anything useful
isn't on that screen yet.
And I'm guessing that no one can tell me within five seconds
where the useful line in that either is.
So this is-- this talk is basically how to not do that.
How do we get away from that?
And the one line answer is use C++ better.
If you-- if you're using the C APIs, which
is what most people do, it's really tricky.
You end up with a sort of Go To Fail style,
or you have this nested IF style that we had there.
And there are a lot of special cases
as well, like I'm trying to throw an exception,
but there's already an exception pending.
What do I do there?
How do I chain that to be the cause
of the previous exception?
So don't write that in every single JNI method.
Write that once.
And in particular, have classes that let
you use a string as a string--
use a J string as if it's a substring.
Similar for arrays-- you don't want
to be having to deal with a J byte array
when you could just use operator square
brackets to just use it like a normal array.
Local references, too, and there's
a long list of other things.
But the strings and primitive arrays, I think,
are the two major ones.
Most of the benefit you get is from that.
Exceptions-- harder than they look,
and the sort of raw primitives you get in JNI
are not super useful.
The-- they expect you to find the class yourself.
They expect you to create an instance.
If you want to actually include a proper detail
message or a cause, you end up doing weird things like,
I need to find the constructor for my--
for this exception, and then I need to invoke the--
blah, blah, blah.
It's a lot of code, especially if you
deal with special cases, so having a function that
just takes a PRINTF style format string is a huge relief,
and great.
So I've been talking about this kind of in the abstract.
I've been saying, you should do these things.
There are many choices that you can use for this,
and I think a problem a lot of people
have is they get hung up on what's the exact perfect way
to do this.
What's the best?
Doesn't matter.
Any of these are better than writing the kind of code
that we saw on the first couple of slides.
Android itself uses Lib Native Helper,
which you can find in AOSP.
It's in the root directory.
There's a bunch of header only stuff
for doing the things I've been talking about,
or if you don't like any of the others on the internet,
you can just write your own.
That-- they're really not that hard.
So what does it look like if you actually do switch
to using something like this?
This is the same code.
This is the same two slides that we had before, now
condensed to one.
I think five seconds is plenty of time
for you to actually see which is the line that
actually does the work there.
You can make this shorter.
You don't actually need to have the style where we have
the constructors, and then we check did that actually work
if you're prepared to use C++ exceptions and do some kind
of transformation, but that's a more advanced topic.
I think this gets you 90% of the benefit for 20% of the effort,
so this is what Android does internally.
This is actually what the code looks
like in Android for that call.
So that was a really simple thing
where there really was just one line
of active ingredient in there, but this scales really well.
And our recommendation is that you actually--
you try to keep your code like that,
so don't mix all the JNI boilerplate
stuff in with your actual code.
Keep those separate in the same way that you wouldn't--
on the other end of the spectrum,
if you wouldn't mix your business
logic and your UI rendering stuff.
Down here, it's similar sort of advice.
Don't do that.
Again, if you want a good example
of this, the Android system OS class,
is implemented exactly this way.
The implementation's super repetitive, really boring,
and that's the way we like it.
It's hard to make mistakes.
I'm running out of time, so I'll just
go through this very quickly.
If you need to worry about old Android releases,
and you have multiple SO files, that can get very tricky.
We recommend that you consider the ReLinker project.
You can find that on Github.
The storing SO file's uncompressed.
That was mentioned earlier in the keynote.
One big library is generally better
than lots of small libraries.
Thank you.
If you have questions, come and find me.
I'll be in-- I'll be doing open hours all afternoon.
So thank you.
[MUSIC PLAYING]