We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Java 9: Juggling the Jigsaw

00:00

Formale Metadaten

Titel
Java 9: Juggling the Jigsaw
Serientitel
Teil
44
Anzahl der Teile
110
Autor
Lizenz
CC-Namensnennung 2.0 Belgien:
Sie dürfen das Werk bzw. den Inhalt zu jedem legalen Zweck nutzen, verändern und in unveränderter oder veränderter Form vervielfältigen, verbreiten und öffentlich zugänglich machen, sofern Sie den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
Identifikatoren
Herausgeber
Erscheinungsjahr
Sprache

Inhaltliche Metadaten

Fachgebiet
Genre
19
20
Vorschaubild
44:46
23
30
Vorschaubild
25:53
69
Vorschaubild
25:58
76
78
79
96
97
AppletDiskrete-Elemente-MethodeWechselsprungStrömungswiderstandGewöhnliche DifferentialgleichungAppletFigurierte ZahlPunktNeuroinformatikElektronische PublikationComputervirusStreaming <Kommunikationstechnik>LaufzeitfehlerSprachsyntheseLambda-KalkülAbstraktionsebeneKlasse <Mathematik>AusnahmebehandlungGanze FunktionGüte der AnpassungProjektive EbeneGrenzschichtablösungGenerizitätModul <Datentyp>Zusammenhängender GraphCASE <Informatik>BeobachtungsstudieMultiplikationsoperatorSymboltabellePhysikalisches SystemFehlermeldungMehrkernprozessorVirtuelle MaschineMusterspracheSpeicherabzugMailing-ListeGrundraumDifferenteBitZeichenketteCompilerProdukt <Mathematik>CodeTermProzess <Informatik>Formale SpracheUmsetzung <Informatik>ExistenzaussageZehnSoftwareentwicklerCoprozessorTwitter <Softwareplattform>ProgrammHalbleiterspeicherFrequenzSchlussregelEndliche ModelltheorieWort <Informatik>AggregatzustandTeilbarkeitBruchrechnungWeg <Topologie>Kernel <Informatik>Schreib-Lese-Kopft-TestStrömungsrichtungGraphComputerspielMereologieEreignisdatenanalyseQuick-SortResultanteKontextbezogenes SystemXMLUML
Diskrete-Elemente-MethodeAppletMenütechnikEndliche ModelltheorieDatenstrukturCASE <Informatik>VersionsverwaltungInterface <Schaltung>BitWort <Informatik>Physikalisches SystemZusammenhängender GraphParametersystemDifferentePunktQuick-SortKlasse <Mathematik>Arithmetischer AusdruckBrennen <Datenverarbeitung>Produkt <Mathematik>AggregatzustandProgrammbibliothekHalbleiterspeicherFlächeninhaltProzess <Informatik>MeterComputersicherheitZahlenbereichKartesische KoordinatenFundamentalsatz der AlgebraGraphMereologieExistenzsatzFunktionalAutorisierungBasis <Mathematik>BildschirmmaskeTaskInstantiierungt-TestDienst <Informatik>Natürliche ZahlProgrammGrundsätze ordnungsmäßiger DatenverarbeitungSichtenkonzeptZeitabhängigkeitRechenschieberSelbst organisierendes SystemSchreib-Lese-KopfAppletMaschinenspracheKomponententestBimodulRekursive FunktionMultiplikationsoperatorWiderspruchsfreiheitVirtuelle MaschineInformationLaufzeitsystemFormale SpracheSystemplattformSoftwareschwachstelleFramework <Informatik>GeheimnisprinzipFitnessfunktionKategorie <Mathematik>KonfigurationsraumDatenfeldOntologie <Wissensverarbeitung>DatenverwaltungSoftwareentwicklerCodeBildschirmsymbolEvoluteSpezielle unitäre GruppeSkalarproduktLaufzeitfehlerMinkowski-MetrikMini-DiscFeuchteleitungWeb-SeiteEinsPackprogrammRandwertGüte der AnpassungSoftwarewartung
Diskrete-Elemente-MethodeInterface <Schaltung>BimodulModul <Datentyp>Jensen-MaßBetafunktionAppletInformationCILFaktor <Algebra>UnendlichkeitDeklarative ProgrammierspracheBimodulKartesische KoordinatenElektronische PublikationZusammenhängender GraphSystemplattformAppletKlasse <Mathematik>Quick-SortGraphComputervirusPhysikalisches SystemStandardabweichungUmwandlungsenthalpieCOMCodeGruppenoperationObjekt <Kategorie>MAPModul <Datentyp>DateiformatRegulärer GraphProgrammbibliothekGrundraumHyperbelverfahrenSchnittmengeKonfigurationsraumInformationLuenberger-BeobachterBaum <Mathematik>Endliche ModelltheorieMereologieSchlüsselverwaltungFormale SpracheMultiplikationsoperatorGüte der AnpassungVollständiger GraphMinimumMathematikApp <Programm>ProgrammierspracheSampler <Musikinstrument>GraphentheorieValiditätEinsMaschinenspracheLaufzeitfehlerLaufzeitsystemBitVerschlingungVerkehrsinformationVersionsverwaltungAggregatzustandBasis <Mathematik>Weg <Topologie>BildschirmmaskeMomentenproblemPhasenumwandlungWasserdampftafelGarbentheorieHalbleiterspeicherNichtlinearer OperatorProzess <Informatik>Profil <Aerodynamik>VererbungshierarchieSichtenkonzeptKlassengruppeBayes-EntscheidungstheorieDatenmissbrauchOrdnungsreduktionLeistung <Physik>Likelihood-FunktionPhysikalische TheorieAbstimmung <Frequenz>Abgeschlossene MengeIteration
Jensen-MaßBimodulAppletDiskrete-Elemente-MethodeModul <Datentyp>Formation <Mathematik>DatentypInformationLoginTypentheorieFehlermeldungMetropolitan area networkThreadElektronische PublikationMagnetooptischer SpeicherBetafunktionLaufzeitfehlerBimodulAppletTypentheorieKonditionszahlBasis <Mathematik>CodeApp <Programm>ErwartungswertDatenstrukturGeheimnisprinzipKlasse <Mathematik>MereologieLoginInformationsspeicherungDeklarative ProgrammierspracheFehlermeldungProgrammbibliothekElektronische PublikationKategorie <Mathematik>VersionsverwaltungKonfigurationsraumBefehl <Informatik>GraphSampler <Musikinstrument>Physikalisches SystemLesezeichen <Internet>Luenberger-BeobachterNeuroinformatikMultiplikationsoperatorJensen-MaßAuflösung <Mathematik>Bildgebendes VerfahrenKartesische KoordinatenZeiger <Informatik>VerschlingungFormation <Mathematik>GruppenoperationAlgebraisch abgeschlossener KörperCodecCompilerModul <Datentyp>MaschinenspracheGraphentheorieEndliche ModelltheorieRechter WinkelProfil <Aerodynamik>Konstruktor <Informatik>DatenbankFrequenzTabelleMultigraphHalbleiterspeicherFigurierte ZahlSchnittmengeGRASS <Programm>MAPIterationEinsOrdnungsreduktionGesetz <Physik>KreisflächeWort <Informatik>ExpertensystemDimensionsanalyseKernel <Informatik>MusterspracheFlächeninhaltMessage-PassingRechenbuchOffene MengePhasenumwandlungBildschirmmaskeTwitter <Softwareplattform>ValiditätBitInverseOrdnung <Mathematik>Physikalische TheorieRechenwerk
AppletDiskrete-Elemente-MethodeBildschirmsymbolFinite-Elemente-MethodeGewöhnliche DifferentialgleichungQuellcodeModul <Datentyp>SpezialrechnerBimodulPhysikalisches SystemGeheimnisprinzipVerzeichnisdienstInstantiierungMultiplikationsoperatorMaßerweiterungPunktSchwingungWort <Informatik>Kernel <Informatik>Physikalische TheorieNatürliche ZahlVersionsverwaltungStandardabweichungResultanteBildverstehenBitEndliche ModelltheorieDateiformatAnalogieschlussProzess <Informatik>Schreiben <Datenverarbeitung>Rechter WinkelEnergiedichteRechenwerkSensitivitätsanalyseKlasse <Mathematik>MinimumDienst <Informatik>SatellitensystemProgrammbibliothekPhysikalisches SystemBildschirmmaskeGraphMathematikMereologieInnerer PunktKartesische KoordinatenDateiverwaltungElektronische PublikationGlobale OptimierungQuick-SortBitrateZellularer AutomatSystemplattformRichtungFigurierte ZahlMinkowski-MetrikDruckverlaufQuellcodeVererbungshierarchieSummierbarkeitKategorie <Mathematik>Interface <Schaltung>BinärdatenGebäude <Mathematik>RandomisierungSampler <Musikinstrument>VirtualisierungPlug inBimodulRechenschieberLambda-KalkülMigration <Informatik>SchaltnetzKonfigurationsraumGeheimnisprinzipCodePatch <Software>AppletSkalarproduktSondierungStreaming <Kommunikationstechnik>Bildgebendes VerfahrenProgrammierumgebungKontrollstrukturApp <Programm>MAPFreewareComputeranimation
SpeicherabzugGoogolComputeranimation
Transkript: Englisch(automatisch erzeugt)
OK. Hello. Let's get started, shall we? This is the last talk of the day. Yay. Tom, you haven't even been here.
So this is about Java 9, Juggling the Jigsaw. My name is Mark Reinhold. I work on Java, as I have for many years. So speaking of many years, Java is, my goodness, 20 years old. Well, now it's actually a little over 20 years old. I think Simon Ritter pointed out on Twitter, just a few days
ago, we have the actual 20th anniversary of Java 1.0 being released on January 26, I believe it was. So the birthday exactly finally passed. 20 years. How did Java survive this long? What methods have helped it survive?
Well, one big one is the conservative manner, a fairly conservative manner in which it's been evolved. Our general method here has always been to identify a pain point as something that's making it hard to use the platform, figure out what the missing abstraction is, and then design an abstraction that addresses the pain point
and hopefully fits in well with everything that we've already gotten. So the missing abstraction might be really simple, a missing method, a missing class, maybe a package, whatever. It might be big. It might be something big and deep, like generics or lambda, or something of that nature.
Now, the goal here is not to keep up with fashion. I remember having conversations in the early 2000s where people would say, oh, look at C Sharp. It has all these cool language features. You've got to add all of those to Java right now. Well, no. The point has been to improve developer productivity,
make people more productive, make programs more efficient, and not just keep up with the latest trends. So we've always tried to stay true to Java's core values of readability and simplicity and universality and compatibility.
So just to talk about a few of the more obvious examples, in Java 5, we did generics. Why did we do generics? Because they were cool? No. We did them because working with collections was just extraordinarily painful. They were basically dynamically typed. You make yourself a list of strings, and you pull a string out of it,
and all the compiler knows is, oh, it's an object. So you have to cast it to a string, and you miss a cast, and you get a runtime exception later on, and it's just too tedious for a word. So that kind of problem was the pain point that motivated generics. In Java 8, we introduced lambdas.
We introduced lambdas because they're cool. We introduced lambdas because it's not an accurate list pattern. We introduced lambdas because it was just too painful to abstract over code as data. We did abstract too hard to abstract over behavior. Sure, you could do it with inner classes,
but who actually wants to code with inner classes? So there we got lambdas enabled, not only for compact code, but enabled the streams API, which in turn enables a lot of computation on multi-core processors to be expressed in a fairly short amount of code.
And that's great. So in 9, we're trying to address two different pain points. One is the riddle and error from class path. And the other is the massive and monolithic JK. We think the missing abstraction,
the common solution to both of these problems, is modulus. So that's what we've been working on in Project Jigsaw for, oh, a while now. So I actually started working on this project in the summer of 2008. As my colleague, Stuart Marks, would observe,
that was an entire stock ticker symbol ago. So yeah, it's been going on for a while. But it is a long-term investment. So let's look at each pain point in turn. The class path. So probably everybody in this room
knows about the class path and its pain. If you don't, you can look it up on Wikipedia. Jar hell. Jar hell is a term similar to DLL hell, used to describe all the various ways in which the class floating process can end up not working. Yeah.
Here's a class path. This is for an actual system that actually is used in production quite a bit to do serious computation. This is the Hadoop class path. Now, Hadoop, if you look at it, it's actually a really well-engineered system. We've spent some time studying it,
using it as a case study for modularization. It's clear that they've tried to keep the components logically designed, reasonably separated, so good separation of concerns and all that stuff, so that it's easy to evolve and maintain. But nonetheless, when you go to run the Doot,
once you get through all the startup scripts and everything, this is the class path that you're using. There are 110 jar files on this class path. I've seen class paths much longer than this. In Oracle products, it's scary.
Anyway, so you could ask some questions about this class path. Is anything missing? Yes. Probably. Are there any conflicts? Yes. There are definitely conflicts in here. If some of the APIs and some of these Hadoop components
are actually meant to be eternal to Hadoop and not used by outside code, are they being used by outside code? Probably. Who knows? And if the answer to one of these questions is not a happy answer, when will you find out? Well, you'll probably get a runtime exception.
You might get a runtime exception. You might get a wrong answer. You might never find out. Who knows? So the fundamental problem here is that the class path for once we have an abstraction that's well-linked, it's the class path. It's the class path, not the component path. The class path is a way to look at classes regardless of what component they're in
or their intended use. So it really is, you know, the VM looks at, you know, the fact that something's in foo.jar is irrelevant to the VM. It just starts at the front and then looks at the first jar file and the second and third and the fourth of it until it finds a class, or it reaches the end
and throws a class that's not found exception. So jar files are not components. They're just containers of classes, undifferentiated. When you think about it, it's amazing that systems this large and even work. Class path.
Monolithic JDK. So there are several aspects of pain around the monolithic JDK. One is that, well, you can't stick it into small devices. Small devices these days are generally a little bigger than the small devices in 2008 even, when we started this project. But it's still an issue.
A lot of these devices have processors that are perfectly capable of running an SE class virtual machine. But when you're putting one of these devices in something that's going to be manufactured in tens of thousands or millions, you don't necessarily want to pay for the memory
to carry around a full JDK when you're only going to use a little bit of it. Now it turns out this is also a problem even on big devices. Sure, a machine like this has lots of memory and lots of disk. But if you're trying to cram as many Docker containers or whatever into it, if each container has its own full JDK
but your application is only using a teeny part of it, then that's a waste of space. Another aspect of the monolithic system is that, well, it's been developed as a monolithic system from the very beginning. This was the modular graph we came up with when we first
started modularizing the JDK itself. Now, over the years, we tried on kind of an informal basis to prevent stupid kinds of dependencies. I remember a case, and I think it was 1.2, where somebody thought it would be a good idea to put in Java-line system some methods to return
AWT icons for the running application. Fortunately, we saw that and scratched our heads and thought, no, that's not a good idea. So there was a fair amount of informal enforcement of a modular graph that didn't exist except maybe notionally in our heads.
So since we never had tools to define proper components, people could use just what they needed. If you were here this morning for the talk that Valibor and Rory gave, they noted six deprecated methods. Methods that were deprecated in 8 and are being removed in 9. They're being removed in 9 because they made it impossible to simplify this modular graph because there
was an unfortunate dependence on something that's basically inside the AWT. So anyway, we're trying to build a clean modular graph. We've got this model with a system. Is the class got the right tool for the job
to deliver the final result? Well, no. JAR files aren't components. You have the same kinds of questions you can ask. Is anything missing? How do you ensure consistency in building it from compile time to runtime? Is it safe to change our tools? We really don't want to have to ask these questions of the platform itself.
The platform itself, of all things, should be the thing that we understand in the deepest fashion. So it's a monolithic system. It's also a monolithic system without boundaries. There are lots of APIs in the JDK. Some of them are internal and some are not.
The ones that are internal have been named by convention. They either start with sun.star, or they have internal somewhere in the name. They are, sadly, often used by libraries and applications, despite the fact that we have been putting up warning signs for many, many years.
Here's a page from the internet archive. Let's see. What was the date? Ah, yes. February 15th. You can see this is 1998. Why developers should not write programs that call sun packages. In fact, such a program is not guaranteed to work, even in future versions, on the same platform
if it uses one of these unsupported parts of, did this help? Well, yeah. Might have deterred a few people, but you know. Having said that, I understand, and I think most of us
who work on the JDK understand there are sometimes legitimate reasons to go use internal APIs if it's for something that you really have no other way to do, maybe short of writing native code or changing the JDK itself. But what's sometimes frustrating to those of us who work on the JDK is people who are not just,
you know, lazy programmers in a good way, but lazy programmers in a bad way. Oh, I need to decode some base64. Oh, look. Sun does base64 to code. Base64 to code. Oh, I'll use that. Sure, no problem. Oh, I'm not supposed to use it? Ah, whatever. I'll use it anyway. So this has all been a significant maintenance
burden for those of us who work on the JDK. It makes us fairly conservative about changing what should have been internal APIs. It makes evolution difficult. Another issue is, well, it's difficult to secure the platform.
You might have heard of Java security. It's been a problem. It's a lot better now than it was a few years ago. One aspect of that problem is that there just aren't boundaries. If you look at all the packages in the Java runtime environment, well, a bunch of them, if they start with Java dot, yeah, you're allowed to use those.
There are a bunch that are dot internal. There are a bunch that start with sun dot. And there's no way. I mean, never mind lazy developers writing code to use these. There's no way to allow access from one of these packages
to one of these internal packages without also giving access to one of these packages to everybody else. Because all we've got is package privates, right? So what do we do? If you're trying to run with the security manager to maintain a secure environment, you wind up depending on a thing.
There's one method in Java like security manager called check package access. Now, that one method needs to be invoked by any code in the JDK that might access one of these internal packages. Because it's the only way to prevent sandboxed code from accessing code in these internal packages, which
can do all sorts of interesting things. You get access to some of this gun safe, and away you go. The thing about check package access is if you forget to call it somewhere, it's not going to be obvious. It's a little bit like the memory barriers Andrew was talking about this morning. All your unit tests could be totally fine.
You could even run and run in production for a while. But until you're up against an actual adversary, and we've seen some very clever adversaries, you won't find out that you're missing a check package access at all. And it turns out three of the five zero-day vulnerabilities
that have been discovered since Java 7 GA were due to the same check package access calls. This is not a happy place to be. All right. Finally, all of the system performance. The peak performance of Java these days, of course, is generally very good.
We often beat C++. But startup performance continues to be a frustrating problem. All of the stuff to initialize and all of these weird random interconnections, there's a lot of work that happens that you usually don't need to do. But because it's a monolithic system, you do it.
All right. Monolithic system class path. The proposal here, we think at this point, the missing abstraction, the common solution to these problems, is to introduce a concept of module to the platform. So as proposed, this is not a layer above the platform.
It's not just a library or a framework that you download from Maven or whatever and just use. But it's actually a fundamental new kind of program component that's expressed in the language and implemented in both the runtime system and the virtual machine. It goes well beyond the class path to provide two key properties. One is reliable configuration.
The other is strong encapsulation. So how do modules fit into what we already have? Well, the ontology of container-like concepts in Java, we've got classes and interfaces. You can organize methods and fields into classes and interfaces.
There's recursion here, right? You can also organize classes and interfaces into classes and interfaces using nested classes, if you're into that sort of thing. You organize classes and interfaces into packages. And now, with modules, you've organized packages into modules, at least at the Java level.
So a module is a container of packages. A module describes how it relates to other modules. So it names the modules upon which it depends. And it exports specific of its packages for use, but only by the modules that depend.
Now, how do we define a module? Well, we write some code. Here's a definition of a module. It says, here's a module, and its name is com.foo.bar. This is a module declaration. You write this in the Java programming language.
It names the modules upon which it depends. So we see here com.foo.bar requires com.foo.baz. It exports specific packages for use by the modules that depend upon it. So it exports com.foo.bar.alpha and com.foo.bar.beta.
Got any wild cards? No. Where do module declarations go? Well, it's Java code. So you stick it in a .java file. By convention, they go in files named module-info.java, following the tradition
of package-info.java. The dash is there because that makes it not be a valid class name. So tools won't get confused, and people won't get confused. Either. What do we do with this? Well, what do you do with the .java file? Compile it. Very good. Yes, you compile it.
And what do you get? You get a module-info.class. They're usually really teeny, but that's OK. So module declarations are in the language. That makes them available in all phases, from compile time to runtime.
It also makes them independent of the artifact format. We could use these in jar files or whatever comes after jar files. And it also fits in nicely with current build pipelines. We don't need to teach, change all the tools for some new kind of file that sits on the side and somehow has to be tracked along with everything else. It's just another .java file, another class file.
OK. You compile your module info. You compile a bunch of regular Java classes. What do you do with them to package them up to make them a module? Well, we could have invented a new format. But we think a better solution for most kinds of code will be things that we're calling modular jar files.
So a modular jar file is a jar file. It has a module-info.class, and it's rude. But otherwise, it's the same old thing. You've got class files. You've got a manifest. You can stick other stuff in there. The beauty of modular jar files is that if you build them properly,
then if you're, say, a library maintainer, you can publish the same jar file that can be used on the class path on Java 8 and as a module in Java 9. In Java 8, we'll just ignore the module info class file. In Java 9, let's see it and use it and treat your component as a module.
All right. So we've got our confu-bar module. It requires confu-baz. Here's the confu-baz module declaration. It exports a package. And suppose we've got confu-app or actual application. It requires confu-bar and initial SQL.
It doesn't export anything. It's the application. It doesn't need to export anything. OK. What about platform modules? This suggests there ought to be a platform module for java.sql, the JDBC API. What module has java.line object in it?
Well, we use the same kinds of declarations to define all of those. So let's look at this picture again. This is where we started. The red thing up here, this is the base module. Basically, the module that has java.line object in it. You always have to have the base module. This was our initial attempt at the module graph for the JDK.
If you just wanted to write the trivial hello world app, how many modules do you think you would need? Well, and of course, you do that by looking at base and taking its transit enclosure.
So to print hello world, I need Jack's P. I need Corva. I need a scripting engine. Sure, why not? Maybe some JavaScript after hello. So this is an example of the kinds of technical debt you find in large systems.
Surprise, surprise. So after many years, much of which I did not do, my colleagues did, we threw tricks both obvious and non-obvious. And there's a whole other talk, at least, in how to do this sort of thing. We eventually wound up with a much cleaner module graph.
So this is close to probably what will be proposed as the Java SE9 standard module graph. So this is showing all of the modules that comprise the SE9 platform and their relationships. This is the transitive reduction, if you remember your graph theory.
So there are more edges in the full graph than appear here. But this one fits on the slot. So base is at the bottom. It doesn't depend on anything else. Java SE is at the top. You could write your app and just say, oh, yeah, I require Java SE. You'll get the entire platform. And you could just ignore the fact
that there are modules underneath it. So the base module is defined by a module declaration. The first part of it, it's a bit longer. Key things about the base module. Well, every module implicitly requires Java.base.
If you write your own module declaration and you don't need to write requires Java.base, you can if you want. But you don't need to. It will be inserted by the compiler for you. Java.base is the only module that doesn't require any others. It's also, interestingly, the only model that's known specifically to the language in the VM. So all the other models in that graph I showed you,
yeah, they're there at runtime. They're part of the runtime system. But the VM has no clue about them until they're loaded. So we've got this from Java.base. We've got a bunch of other declarations for all of the other modules. How do we package up these platform modules? Well, some of them, and generally more
the ones near the bottom of the graph and at the top, have native code in them and license stuff and man pages and other kinds of things that you typically don't find in JAR files. So we invented a new format. It's a pretty simple format. We call it JMON.
It's basically JAR files on steroids. You can't use a JMON as a JAR file. In fact, you can't even really use it at runtime. It's meant strictly as a transport format. At the moment, we're using the zip format because it's convenient. We might change it to some better format later. But it breaks out classes from executables,
from native libraries, from configuration stuff. And it basically gives us everything we need to deliver a JDK build not only as an entire image, but as a set of modules that you can mix and match as you need. OK, so we've got our application library modules.
We've got the platform modules. Taken together, we think of these as the universe of observable modules. If we were looking at the femtosecond before JDK and startup, OK, boom. Here are the modules we might consider. If we're about to invoke the compiler, here are the modules the compiler might consider as it's going to compile some code.
So to make use of the observable modules at either compile time or runtime, we have to figure out how they relate to each other based just on what this app needs. Now, remember your graph theory. What's the computation we're going to do? Transitive closure. Anybody?
Viewer? Transitive closure. Yay. So we're going to build a graph. Kung Fu app requires Kung Fu bar and Java.sql. OK, here we go. Kung Fu bar, Java.sql. Oh, yeah, it requires Java base because everything requires Java base, remember?
But we don't have to write it. Kung Fu bar, in turn, requires Kung Fu BAS and Java base. Kung Fu BAS doesn't require anything. It's just Java base. Java.sql requires logging, everybody's favorite logging. And Java XML.
And it requires Java base. And logging requires Kung Fu base. XML requires Java base. OK, there's our initial module graph. So the module graph defines the notion of readable modules.
And readable modules are the basis of reliable configuration, that first property that I mentioned. Reliable configuration lets us tell when things are missing. It lets us tell when there are conflicts. For example, suppose in the Kung Fu app, a module declaration we wrote requires Kung Fu whatever.
But there actually isn't a Kung Fu whatever at compile time or run time. Well, what happens at compile time? You get a helpful error message. Error. Module not found Kung Fu app with a pointer to your mention of Kung Fu whatever.
Suppose you manage to compile this through some mistake or subterfuge or work in this way. You go to run it. Error occurred during initialization of VM. Module Kung Fu whatever not found required by Kung Fu app. There you go. Rather than waiting until sometime
after your application's been running for 10 minutes, you find out right away that something that's going to be needed is missing. Explain the command line arguments. The command line arguments, sure. For Java dash NP in the Jigsaw build, there's a concept of module path.
It's a class path, but it's for modules. And dash M says the main module is going to be the one Kung Fu app go find its main method, which is declared out of band in a manner that I can explain later if we have time. So that's a reliable configuration.
We've got our module graph. What about strong encapsulation? Well, remember the other kind of statement in a module declaration is an export. So we can walk through those and annotate our module graph. Kung Fu app, well, it's the application, so it doesn't export anything. Kung Fu bar exports Kung Fu bar alpha and Kung Fu bar beta, so we'll add those here. Baz exports Kung Fu, BazMumble.
SQL exports Java.SQL and JavaX.SQL. Logging exports logging. XML exports JavaX.XML and a bunch of other stuff. And then we're done. Oh, wait. Java.Base. Yeah, that's important, isn't it? OK, Java.Base exports a whole store of packages.
OK, so the exports define the notion of accessible types. Some code in one module can access and type in another module. If the first module reads the second module, there's an error. And if the second module exports the package containing that type,
both of those conditions have to be true for access to be granted. And this is the basis of strong encapsulation. Now again, as with readable types, we try to get detailed error messages when things go wrong. Imagine that the Kung Fu bar module
has an internal package called Kung Fu bar beta internal. And there's some public beta nipple class in it. If in Kung Fu app we import that class and even go and instantiate it, well, at compile time, we will get an error.
Beta nipple is not accessible because package Kung Fu bar beta internal is not exported. There's the instantiation. You can now go fix. If you actually manage to compile this because you have to do this in an out of base compilation thing and you run it, you will also
get a runtime exception, a legal access error. And this is fairly long, but it's long so that you can go fix the problem. Class Kung Fu app made in module Kung Fu app cannot access class Kung Fu bar beta internal beta nipple, module Kung Fu bar. Kung Fu bar beta internal is not exported to Kung Fu app.
If you did this right, you could do a whole Dr. Seuss quote in this area. So to recap the essence of the module system, we have module declarations written in the Java programming library. They're compiled into module info.class files. Modules are packaged into modular jar files,
or if you're working on the JDK or something else that has to have native code and stuff in it, jmod files. We have the notion of observable modules. We start with that in any particular phase. We use the concept of readable modules to construct a module graph. That gives us reliable configuration.
We interpret export statements to determine accessible types, which give us strong encapsulation. And these two properties are enforced uniformly at both compile time and run time. So the configurations of large systems are essentially correct by construction,
or they're way more correct than they are today. OK, going back to our pain points, let's see how modules address them. Size. So as we've seen, modules let us use only what we need. But how does that work out? If you're trying to fit something into a small system and it's great that we can construct
this module graph at run time, but if the observable modules include the entire JDK, does that mean that the entire JDK is still going to have to go onto our small device? Well, no, because we're introducing a new tool. So a new optional step between compile time and run time is link time.
Around 20 years ago, when I first started working on Java, I remember asking James Gosling, so does Java have a linker? And the answer to that, of course, was, well, no, of course not, because it's all dynamically linked all the time. Well, we're introducing a linker. It's optional, but it's a linker,
so obviously it has to be called jlink. Jlink is a tool that consumes jar files and jmod files. It runs the resolution and configuration computation to create a module graph, and then it puts into a custom JRE image just the modules that
are in that graph. And it can also do a bunch of pre-computation of other stuff. So you can make a custom image that has just what you need, if you only need java.base, because you're going to burn the hello world app onto your atom board, and you can do that. For performance, we're doing some direct work
around performance. A big part of what we're doing for performance in 9 is enabling future stuff. So we don't expect dramatic performance improvements in 9, but we're trying to lay the groundwork for some dramatic performance improvements later on. Dalibor touched on this in his session this morning.
We're changing the structure of the JK, the Java runtime environment, as delivered. Here is a summary of what it looks like today. There's a bin directory with commands in it, a lib directory with other stuff in it, including rt.jar and .sos and random properties things and whatnot. We're changing this in 9.
In fact, we changed this in 9 quite some time ago. There's now properties files and other kinds of configuration files that are meant to be possibly edited by humans, but actually often aren't, are going in their own configuration directory,
so they're easy to find. Native stuff is all going into the lib directory. Those need to be at least somewhat easy to find, because some applications link to these directly if they're using the JNI invocation API. And then the rest is dot, dot, dot, which on this slide is shorthand for never you mind.
These things are gone. Dalibor mentioned these this morning. The endorsed standards directory is gone. The extension directory is gone. They added a lot of complication with some surveys and looking at a bunch of existing code out in the world, we found out that rt.jar is gone.
Of course, obviously, a JRE is going to have a bunch of classes baked into it, but they're in a file in dot, dot, dot. The format of this file is not documented, except in the source code.
And that's intentional, because we want to preserve the right to change it even in a minor or a micro release. We need to change it in a patch release. We will do that. Do not write code that depends on the format of anything in dot, dot, dot. Yes, the same kind of warning I made at the beginning,
but you know. At this level of the system, there's no practical way to prevent people. If you really want to, yeah, you can go and dig into this. Feel free. But do not come crying when the next update release breaks your app.
And both at Sound and Oracle, we tell the same thing to customers. Oh, you want to escalate an issue for your use of a deeply internal API? At Sun, we would usually say no at Oracle. It's like double the price or something.
All right. So excellent question. There is, in fact, an API. Yes, there is a public API, and it turns out, well,
it's actually just an instance of an IO file system. So if you're writing an IDE or some other kind of tool that needs to inspect the classes in the JDK,
you can get access to this Neo virtual file system that surfaces the stuff that used to be in r2.jar. And you can explore it. It's indexed by both modules and packages, so you can find things efficiently. This went into 9 over a year ago, so most of the tools by now have it out of the tool.
And that is an interface that we intend to support for the next 20 years, at least, probably. So with this new format, J-Link creates all of this for you. And J-Link has plug-ins that can do interesting kinds of optimizations. That plug-in idea is how we expect a lot of future work
to be expressed ahead of time. Compilation can be expressed as a plug-in. We already have plug-ins that will do more compression than usual if you're really trying to save on space and things like that. All right. I am actually running short on time. So internal APIs, Dalibor touched on this also
this morning, broadly used internal APIs that are critical, for which you cannot write a replacement into your Java will remain available until they have an effective replacement. Others will be strongly encapsulated. The ultimate workaround is a command line fly. Yes, it is possible with command line flies to probe into anything.
And it's painful when you have to write long command lines. But you know what? To get ready for all of this, yes, run the JDeps tool. Dalibor mentioned this this morning. JDeps is actually in JDKA. So you have JDKA. You have an early version of JDeps. The JDeps that's in 9 is even better.
The JDeps that is in the Jigsaw build is even better than that. So if you really want to get going, then get a Jigsaw build. As to the classpath pain point, well, we're providing tools here. We're providing the tools with which people who maintain a chip code can
get the benefits of reliable configuration and strong encapsulation. Migration has been a very big concern of ours. We're trying to design this so that you can migrate an existing system, either from the top down or from the bottom up, or some combination of the two. And that's tricky. But we're trying to steal some of the tricks that we learned for generic types,
so that you don't have to modularize everything before you can even use modules. It is a long road. We do not expect modules to be adopted as rapidly as some other features, or Java 9 to be adopted as rapidly as some other releases.
Some of the changes are admittedly disruptive, but we think they'll be worth the cost. The nature of the feature, in some ways, is just not that exciting. Lambda was really cool. Lambda was a jet pack. You could explain Lambda at a high level, and then somebody could go write code that uses Lambda,
and uses the Streams API pretty quickly. You didn't have to change much of anything else. You didn't have to get the right version of Maven and Eclipse that would actually change Maven. You had to get a new IDE, probably, to understand Lambda. But the point is, you could get going quickly.
Modules are more of a seat belt. They're a safety feature. If you use them wisely, it will be easier to build large systems. It will be easier to make them go faster, as well as build them more quickly. Jigsaw itself has been a long road.
As I mentioned, we started in 2008, but it's another one of these long-term investments like generic-sore Lambda. It takes time to get right. It takes time to get all the right feedback, because we don't want to put the wrong thing into the platform. But we think it will be a strong foundation for the future. How to learn more.
Jigsaw is at this URL over jdk.com.jigsaw. We've got five JEPs. We've got an entire JSR for the model system itself. We have early access builds. They're now updated not just every week. Unlike the JDK9 early access builds,
the Jigsaw builds are now updated at least once a day, assuming that changes are still happening in the code base. So it's not on every commit, but it's at least once a day if anything did change. I work for Oracle. Oh, did you want to say that again?
There you go. I did not make all those images by hand. Or by any means. And I am two and a half minutes over. Thank you very much.