Java 8 Developer Preview Released
An anonymous reader writes "Oracle has released the first developer preview of Java 8 for the full range of platforms (Windows, Max OS X, Linux, Solaris). Java 8 is a major update to both language and platform with Lambda expressions, method references, default methods, a new Date and Time API, Compact Profiles, the Nashorn JavaScript Engine, and the removal of the Permanent Generation from the HotSpot virtual machine. 'This milestone is intended for broad testing by developers,' Java Platform Chief Architect Mark Reinhold wrote on his blog. 'We've run all tests on all Oracle-supported platforms and haven't found any glaring issues. We've also fixed many of the bugs discovered since we reached the Feature Complete milestone back in June.' Let the bug hunt commence!"
This is the second part of the JDK "Plan B" where JDK 7 was pushed out without cool new features like lambda expressions to prevent stalling language development for too long.
How about 'cool new features' like testing and code audits?
Java 8 will probably be as full of holes as the last iteration.
The fact that Oracle didn't find any glaring issues is hardly a surprise. A better question is whether they would fix them even if they did find them, like that rather glaring security vulnerability that they've just decided to brush off until their next major release last year.
"Knock knock."
"Whose there?"
.
(time passes)
.
.
(grass grows)
.
.
(paint dries)
.
.
.
"Java"
Jvm/core libraries updates are very welcome - but the language level changes are just too late. If somebody can run cutting edge, (s)he probably long time ago switched to Groovy (http://groovy.codehaus.org/), Scala (http://www.scala-lang.org/) or Xtend (http://www.eclipse.org/xtend/). For slow corporate clients, java 8 will anyway not happen until 3-4 years after official release.
Java devs tell this to JS devs a lot. You must fix your problem without changing anything. Warts must stay.
So java now supports default methods for interfaces? In other words "we now support multiple inheritance". Or at least that's pretty close to it. I thought the logic was that multiple inheritance is messy when you have diamond shaped inheritance, or two parent classes that have the same method names, so java only did single inheritance, but then allowed you to do interfaces to sort of simulate multiple inheritance (except you had to write all the code). But with this change, it seems the same as multiple inheritance, with the exception that interfaces cannot include (non-static) variables, only methods. Am I correct here, or am I overlooking something?
auto properties?
Everyone's jumping on the lambda train! Choo Choo! You know what that means! Two years from now all code will be written with nothing but lambdas. All those programmers out there with a new hammer, looking for a nail and all. Don't get me wrong, I just posted up a bit of nitfy sorcery with the new C++11 ones that would have been a lot harder without them. I'm just not looking forward to maintaining any code written in the next couple years. If we actually did design reviews here, I'd have to demand that any usage of them be justified (Kind of like singletons a couple of years ago blah.)
I'm trying to teach myself to set people on fire with my mind... Is it hot in here?
: ) http://svn.netlabs.org/java
Does anyone really trust Java anymore?
Not a troll. Serious here. Since Oracle took over trust has eroded. Have we reached the end of Java dominance in the corporate environment?
Having played with Java 8 I can see that it can be used in two ways. One is using a few of the enhancements but basically sticking to the procedural/OOP paradigm. The other is to incorporate the functional programming paradigm. I can see a lot of conservative Java teams just sticking to what they know - which will be interesting because at some point they will have a new developer start using the functional capabilities. I can see the culture clash, with the old team members saying "we can't support this" and the new members saying "but its more efficient and inherently more supportable as the functional paradigm uses immutable objects and avoids side-effects.
Whose their?
You're a temporary arrangement of matter sliding towards oblivion in a cold, uncaring universe
I mean.... wasn't that their whole main argument against operator overloading? (the other argument, that operator overloading makes for unreadable code can be shown to be a red herring).
File under 'M' for 'Manic ranting'
learning from JavaScript ;)
It makes a huge difference in readability when transforming collections. Difference between (Xtend example)
people.filter[age >30].forEach[println(it)]
and
people.filter(new Predicate1() {
public boolean match(Person p) {
return p.getAge()>30;
}
}).forEach(new Procedure1() {
public void run(Person p) {
System.out.println(p);
}
});
in readability and ease to write goes outside of what I normally call 'syntax sugar'. Going this way, most languages can be defined as syntax sugar over assembly...
The 1990's called - they want their joke back. #tiredmeme
Modern JVMs are fast enough, most people can't tell the difference between them and pure native code.
No colour or religion ever stopped the bullet from a gun
I don't really get the point of adding such a major syntax-changing feature to the language for the sole purpose of syntactic convenience.
While there are definitely a lot of judgement calls and tradeoffs to consider when designing a language, syntactic convenience is a big part of why we use programming languages to begin with.
I mean.... wasn't that their whole main argument against operator overloading? (the other argument, that operator overloading makes for unreadable code can be shown to be a red herring).
As you indicate, the operator overloading argument was/is bogus. I suspect that everyone tried to misuse the feature when it was introduced with C++, in much the same way that everybody used a dozen different fonts the first time they ran a WYSIWYG word processor. The people who got bit by this bad code went on to write best practices and coding standards that breathlessly prohibited operator overloading and Java followed suit. So you have dumb things like == testing for reference equality of strings, Vec3D classes that you must .add() and .subtract() instead of + and -, and naturally-ordered things that you can't compare with < and >. Hopefully one day Java will reverse this bad decision too.
-1, Too Many Layers Of Abstraction
Your Java example is needlessly convoluted. Most people would just write this, which is only a little more verbose than your Xtend code:
for (Person p: people) {
if (p.getAge() > 30) System.out.println(p);
}
Did you warn them?
Scale your application enough... The difference might bite you. But yeah, it's not as it's used to be.
uhm...
They hung up before I got the chance :(
No colour or religion ever stopped the bullet from a gun
Yay! A new Date and Time API! As if the first two weren't enough. Java is going to collapse under its Date/Time, I/O, and threading APIs.
How much code are you going to write for that by anon classes?
MyIterable .Where(item => item.Name.Contains("box")) .Take(100) .GroupBy(item => item.Price % 1000) .OrderBy(group => group.Key) .Select(group => Tuple.Create(group.Key, group.Count()))
like, 50 lines?
Your Java version misses the point. The parent's style is extensible and composable, and declarative rather than iterative. This is a general trend as it leads to cleaner code, with more re-use of functionality.
OP asked why lambdas are better than anon classes. Example I gave is indeed simplistic and can be solved by snippet you gave - but as soon as you start adding some transformations, sorting, group by etc, plain java starts to be quite verbose. Still considerably better than 'functional' approach using anon classes of course.
So yes, lambdas are of smaller use to people who are not using anon classes in first place and don't want to switch to functional approach. In java 8, main rationale for adding them was for parallel collection processing, which is pretty tricky to express in plain java.
Does your computer still have 640k of "base" memory? You need to enable "expanded memory" to run modern applications on your machine.
On the contrary, GP nailed it. When you start extending and composing and declaring too much, you lose the impressive and straightforward readability of GGP's example and end up with write-only code like Perl (to many people who are less capable than you).
If you're smart, functional programming is quite fun. If you have to work with someone who is, um, less smart but still forced to write functional code in your shared project, God help you man.
tldr; we don't all work in the upper echelons of the programming world
Javascript? Solve real problems? Bwahaha.
Keep on trollin'
it's the inconsistency that I don't understand
File under 'M' for 'Manic ranting'
Is Swing thread-safe yet? TL:DR //java developer
Hey... If its good enough for mathematical ring or group structures to have to explicitly spell it out instead of using arguably much more intuitive math operators, why should having to use anon classes instead of lambdas be any different?
File under 'M' for 'Manic ranting'
Who's their?
All I want is a secure system where it's easy to do anything I want. Is that too much to ask ~~ Randall Munroe
Exactly! How the hell am i supposed to justify writing a class factory factory to create a factory that creates the class that has the function I need to pass to another function when I can just pass a lambda expression? There goes my KLOC metrics!
Java has jumped the shark and is no longer ENTERPRISE enough for me. I'm going back to COBOL!
Will this release of Java come with an Ask.com toolbar, a Yahoo.com toolbar, or a Google toolbar?
Who's they're?
You're a temporary arrangement of matter sliding towards oblivion in a cold, uncaring universe
Depends. If you are using a PC with 256MB of RAM, you will see the difference quickly and brutally.
Religion: The greatest weapon of mass destruction of all time
Well frankly, "inherently more supportable" is 100% based on who is supporting the code. If you throw in the most elegant functional code on earth on a collage grad who's only learned OOP, then your code is going to have a bad day. Now imagine code where performance, and time trade-offs mean that the code isn't perfectly structured...
Bye!
Adding multiple inheritance and lambda was a mistake. In theory these are great, the specific design decisions are terrible.
Java Generics could have turned out great, but the design was horribly crippled due to backwards compatibility and now Generics causes more problems than it solves. Readability just went out the window.
Similarly with Lambdas, the syntax they chose is hardly readable or familiar to Java developers. Sometimes a slightly more verbose syntax is preferable, so long as it looks more familiar and readable.
I hope they get a strong push-back from the community for these problems.
Like I said, 1990's :P
No colour or religion ever stopped the bullet from a gun
People still use Solaris? Just asking. I might download a free version if I find one.
I doubt there ever was an "official" reason for not having operator overloading except: they wanted the first Java compiler ready pretty quickly.
OTOH it is not an inconsistency, its the insight of being now something like 10 years in the future versus the time when Java 1.0 / 1.1 was made public.
However it is still annoying that we still have no operator overloading.
Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
TL;DR: Sometimes we are forced to work with outsourced Indian programmers.
FTFY.
I use them to reduce bugs, for example, it's not uncommon to have a two-line piece of code that you want to apply to two different variables. Something like this:
height = x * scaleFactor / screenSize + translation;
width = y * scaleFactor / screenSize + translation;
With lambdas you can combine the calculation into a single function, and reduce the duplication (reduced duplication reduces the chance for accidental typing bugs). Of course you could move it into a normal function, but then you have a two-line function you'd have to jump to, instead of just looking at it where it gets executed. That's probably an over-simple example, but if you care you should be able to get the picture.
There are probably other places where lambdas are nice too, but that's what I see as the main one.
"First they came for the slanderers and i said nothing."
I'm not expecting Java to catch up with Scala any time soon...
Called functional programming. It's been around since before 1960; you should look into it sometime.
(Lambdas & lexical closures: Scheme 1975; ML family since 1980s; Haskell; Scala; etc)
Java is only catching up to Lisp and Scheme, 40 years ago. FORTY.
If you want a refresher on higher-order functions, see: http://mitpress.mit.edu/sicp/
Good thing is that it will deprecate Guava. Because young developers like their guava (for loops are fashion faux-pas nowadays), but it looks clunky compared to real support in the language.
It's not just syntactic convenience. Lambdas represent closures, which have different scoping rules and variable capture rules. For one, lambdas just use lexical scope and don't introduce a new scope (which anonymous classes do. Because they are classes).
They can capture certain variables in the scope that anonymous classes can't. It's a bit complex, but lambdas can capture variables that are effectively final, before, it has to be declared final.
Here's an example. Imagine you are in a method of class, you have an external list of other objects that you want to match based on a person's name. You can just use this lambda as filter:
This is a natural expression. Note, that this doesn't work in an anonymous class, because this refers to the anonymous class, not the outer class.
Moving on from this, the new lambdas and functional interfaces allow you create much more generic functional methods. So, you can now write things like
As a C# developer (and secret Schemer, err, Racketeer), functional style programming is really useful and has a big impact on productivity and expressiveness. Sadly, Java Generics and type erasures imposes some limits compared to the C# implementation, but that doesn't discount how useful this style of programming is.
tu'lu' 'Iv?
In Soviet Russia, Java bugs find you!
You need lambdas to do parallel transformations on collections in sane way. Java is claiming to be THE language for mainstream parallel programming (doesn't matter if it is actually valid, but Oracle sells it this way), so they need lambdas.
You need operator overloading to do non-trivial math programming in sane way. Java was never sold as number-crunching platform, so there was no push from within Sun/Oracle for that.
Where are these "Upper Echelons" of which you speak.
You in fact missed the point... Today we need to use gigabytes of RAM to do the same work we did earlier with only 256Mb (or much less). At least in my development school, this means that the current programs are much, much worse than your "ancestors".
Religion: The greatest weapon of mass destruction of all time
You were doing H.264 encoding in 1998?
No colour or religion ever stopped the bullet from a gun
Average developers will continue using Java as forward-thinking engineers use Scala, JavaScript, and other progressive languages to solve real problems faster.
Employed developers will continue to use Java, COBOL, Pascal, or whatever their employer's code-base is written in. This seldom has anything to do with the skill of the developer, and almost everything to do with the cost of converting functional, stable code to a new language. The case to move to a new language must include benefits in excess of the stability of the existing code-base.
Average developers will make a mess of any code-base, regardless of the "new hotness" status of the language.
I could write something witty for my sig, but instead wrote this...
Web apps, etc. ... anything that you can use java for, there's a better faster alternative with far less security vulnerabilities. The world is moving to devices (tablets, smart phones, smart watches, ... smart X). The days of "well I'll make my shitty web app run on device X" are over, customers are demanding high performance and low-suck ... oh yeah and it had better be cheap. Where will java survive, the back-end; but again there are lots of alternatives that are better ... so java is going to be pushed out of that space as well (in time).
Can you explain what problems I wouldn't be able to solve with JavaScript that are solvable with Java? I've yet to encounter any. Maybe you can help me?
However it is still annoying that we still have no operator overloading.
It's very easy to go horribly off the rails if you start overloading operators (or declaring completely new ones!) so if you're going to propose it, for goodness' sake do it by requiring people to implement a proper mathematical structure (e.g., a group, a ring or a field).
"Little does he know, but there is no 'I' in 'Idiot'!"
Whether or not Java was billed as a number crunching platform doesn't change the fact that such number crunching can often be fundamental to the underlying model to some pretty common and often surprisingly useful stuff, especially in the realm of computer graphics, but it arises in a handful of other domains as well. This phenomenon occurs as often as it does because at it's core, all computer programs *ARE* just math.
Or are you suggesting that Java wasn't ever supposed to be used for doing computer graphics either?
And so a linguistic means that manipulates such necessary and often quite customized mathematical constructs in a concise and intuitive way would therefore inevitably be very useful. Whether or not the JVM performs such computations as efficiently at run time as a language designated for hard-core number crunching would is less of an issue than whether or not those computations are easy to read and understand at a source-code level.
Lambdas do nothing but offer a syntactic convenience beyond what was already possible in Java. I recognize that this is a significant issue however, and I don't mean to downplay it's importance, but it's equally the case that operator overloading is not really anything but a syntactic convenience either.
File under 'M' for 'Manic ranting'
I am surprised at the backlash about adding lambdas and some associated features (default methods) that support a more functional programming style.
Firstly, lambdas aren't just anonymous class syntactic sugar, they work differently. Hence, new syntax, that just happens to be more concise. Lambdas and closures are as old as the hills, this isn't some trendy new language feature that hasn't been well thought out.
And, yes, for loops are enough, we know this. But conciseness can help. I have a list of orders, each order has a list of line items. I want to sum their prices up. Sure, the for loop version isn't too bad.
And if we want to choose which orders and which lineItems, we add conditional statements. But, as one codes more and more, you will write code like this a lot. At some point, one thinks about you could somehow capture this "pattern" more concisely? One could go to the GOF and talk about a Iterators, Strategy, etc. But, that's a lot of classes. Functional programming does is give you a different, smaller set of building blocks to capture patterns like these. Let's do a LINQ version in C# of our Java code.
Now, this code is more dense, but if you look at it, it states what you want, not how to get it. I read this as "For all orders for a given customer, select all the line items for which the price is more than 10.0, and give me the sum of the price for those line items). Now, imagine that the orders list is pretty big, and we want to see if a parallel version would do better. PLINQ makes that a breeze.
Now, this isn't as efficient as a hand crafted parallel loop, nor it is magically going to work on a list of orders that can't even fit in one process, but with one change, we can see if we get a speedup, and if it is good enough, and if it isn't, then we can go for a handwritten version. In the era of multicores and parallel programming, a basic understanding of functional programming is very useful as it gives one a different set of tools for how to think about a problem. My apologies for the poor code formatting, but hopefully the ideas still come through.
Skilled engineers who wish to remain relevant and find greater success will educate themselves about new technologies and use whatever tool is best for the job. This isn't about "new hotness" as you put it, it's about willingness to move on from a given technology when superior alternatives exist. Done smartly, there is a great deal of value found in disrupting the status quo. That a project or team uses any given technology doesn't mean it should always be stuck there.
The Java language (not the platform, mind you) is antiquated and difficult to use compared to many new languages that have surfaced (I mentioned two). In its day, Java was among the best languages to get hard problems solved quickly. Today, demanding requirements for scalability and durability are the new normal. You can achieve these in Java, but doing so requires a lot more effort—in no small part to resistance to evolve the language on the part of its maintainers.
Sadly you are wrong. Java8 lambdas offer nothing over anonymous classes because, unlike C#, they only capture read-only variables, exactly as do anonymous classes. It is a sad joke.
Java8 lambdas are significantly more concise. And yes, syntax does matter. If it didn't, we'd be writing things in some dialect of COBOL.
And using custom overloaded operators for appropriately defined classes that mimic ring or group-like structures is significantly more concise than calling named methods, and reads much more intuitively.... yet the syntactic convenience of such notation is not considered sufficient merit to add it to the language.
Yet somehow the syntactic convenience of lambdas is considered sufficient merit over anon classes to add that.
Go figure.
File under 'M' for 'Manic ranting'
I totally agree with you that all the reasons that Java designers ever gave for not including overloaded operators can be concisely summed up as "bullshit".
Even more so in a language that doesn't even have a built-in operator to meaningfully compare two strings for equality - or any other concise way to compare two String objects (at the very least, without repeating either comparand), accounting for any combination of nulls.
Then again, I'm a C++/C#/Python guy, so what do I know?
Will try out the new Java version too and hope it is soon finished. :-D
There are hundreds of uses for operators outside of the field of math. (E.g. adding an element to a list with + and removing it with -)
And frankly I would be already glad if we had operators for BigDecimal. Nearly every business application I worked with the last years ONLY uses BigDecimal. It is so annoying to have to write 5 lines of method calls when a simple READABLE result = input * hoursADay * 4 * daysOfYear * pricePerGwh would be sufficient.
Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
On the subject of operator overloading, having to call isEquals instead of using an operator like == to compare Strings is one characteristic of the language that never really bothered me in the slightest... but that may be only because it reads like what the function is actually doing, (that is, it seems fairly obvious to me from the name itself that it would test for equality between the object and the parameter to the function, and not do anything else).
But having to type somethiing like a.plus(b).times(t).plus(a.plus(b).times(1-t)) instead of (a+b)*t+(a+b)*(1-t), for example, is very annoying. The function specification loses a lot of the notion of exact precedence, and particularly annoying to myself, it does not even *read* the same as the version described with math the formula.
The latter problem could be somewhat abated by renaming .add() to .plus(), .multiply to .times(), and so on... but then one would be using an inconsistent naming convention to operating with mathematical structures, since the numeric types that come with the java framwork, such as BigInteger, use the function names .add(), .multiply(), etc. Even more annoying, however, and to a certain extent regardless of what naming convention is utilized, it is not immediately obvious from the function name whether the function modifies the state of the object it is operating on, or if it returns a completely different one, whereas with mathematical notation, the stateless nature of the operators is explicit in the notion of understanding what the operators mean mathematically. If one wanted both functions... one to modify the state of the object, and another to return a new one, one is forced to adopt a particular naming policy which may not necessarily be intuitive for other programmers who might have to read the code to differentiate them.
And far from being a contrived complex example that would be useful in a small domain of programs, the formula that I described above is actually an extremely common one which can be used for doing a linear interpolation between the values of a and b, whatever their types may be, whether scalars, vectors or almost any other type of mathematical structure, and the pattern is extremely common in animation code.
File under 'M' for 'Manic ranting'
On the subject of operator overloading, having to call isEquals instead of using an operator like == to compare Strings is one characteristic of the language that never really bothered me in the slightest... but that may be only because it reads like what the function is actually doing, (that is, it seems fairly obvious to me from the name itself that it would test for equality between the object and the parameter to the function, and not do anything else).
The main problem there is nulls. You can't just write a.equals(b). For full equality, you have to write (a==null && b==null) || a.equals(b). When one side is a literal, you can turn it around to save the null check, e.g. "foo".equals(b), which still looks silly to me, but the most generic case is really the worst because not only it's verbose by itself, but you have to write the left-hand-side expression twice; so if it's expensive enough, or has side effects, you need to introduce a temporary. Just to compare two strings!
The problem I would have with making == check for content similarity is that there are really two different notions of equality, one of which is to compare only the content of the two objects and the other compares the identity of the objects. If == were to ever mean comparing their content, then there would be absolutely *no* means for comparing identity. This may be perfecty acceptable in a lot of circumstances, but imposing that limitation upon a programmer by making that trait part of the language ultimately makes the language less useful.
File under 'M' for 'Manic ranting'
For immutable types, there's no point in ever comparing identity - there's nothing useful that you can derive from knowing whether you have two references to the same immutable object, or two different ones (since you cannot do anything to that object that would make the difference observable). So having == do value comparison for strings is not really imposing undue limitation on the developer.
On the other hand, I do agree that it's not particularly neat to overload it like that. Object identity is reference equality, and value comparison is object equality. So this is basically like having an operator with variable indirection - sometimes it dereferences its arguments, sometimes it doesn't. That's confusing.
The ideal solution, to be, is to have two separate operators that cleanly separate value and identity comparisons. Furthermore, because value comparison is something that is much more common, I posit that == - or the equivalent operator that uses the standard equality notation - should be a value comparison for both value and reference types; and the object identity operator should have a different name.
Python has got both the design and the naming, in my opinion - "==" and "!=" are always value comparisons, and "is" and "is not" are identity comparisons.
Except, of course, that == is already an identity comparison operation. This would be fine if you were designing a language from scratch. It's anything but if you are wanting backward compatibility.
File under 'M' for 'Manic ranting'
Well, I missed the section that they added the relaxation for effectively final variables for inner classes as well, so yes, this is just syntactic sugaring.
I still argue that the concision of lambda syntax is still useful, even if you don't get full on closures.
You can use one of the open source distributions that were forked from OpenSolaris (more or less): Nexenta, Illumos, etc
ZFS alone makes this more than worthwhile, although you can now have ZFS with FreeBSD, OS X, and even Linux.
you had me at #!
For those interested, the license seems to be GPL+Classpath Exception:
http://hg.openjdk.java.net/jdk8/jdk8/raw-file/tip/LICENSE
I sure as hell can.
How to tell if it's a java app:
* It's doesn't use the OS's look and feel.
* It doesn't use the same font AA and hinting as everything else.
* A simple two-button window will take several seconds to load (instead of 1s), regardless of hardware.
* Memory usage jumps up, even if it's just a tiny console app.
Which has really unusual formatting just to look shorter!
Then the developer should have spent more than 3 seconds developing it.
No colour or religion ever stopped the bullet from a gun
I haven't read through the entirety of the new Java spec, but the most general answer to your question is that to support lambda expressions, a language usually needs to support functions as a first order feature. Right now, if I want to make my class execute some operation provided by the caller, I need to write an interface (or worse a base class). The caller then needs to implement that interface, and so on and so forth.
By contrast, a first-order function doesn't require me to tell the caller anything beyond what they must know. I just write a function that has a return type and parameters, and anything they can squeeze into that pattern they can pass in. For instance, threads right now require runnable with a run method. What if I have a void exec() method already? I still need to write a void run() method. With functions, I don't have to create so many new (and redundant) methods.
No... you do it in java now? are you masochist?
New hardware can do h264 encoding... and other things nicely... if the other concurrent things running are not bloated. Java has never been the less bloated path to implement nothing... is as simple like that.
If developer cost matter more than hardware investment by users, java is option... depends if you can translate the cost to users to save on payroll. With seasoned developers and good tooling the developer cost differential is not that in favour of java or dotnet. the problem tents to be lacks of caring
No... you do it in java now? are you masochist?
My point is about 50ft to your left.
No colour or religion ever stopped the bullet from a gun
I don't dispute that it is useful, but it is less so than it might appear at first sight. IntelliJ IDEA already could automatically collapse anonymous inner classes into lambdas in the IDE, even with Java 6.
The huge disappointment is that they *could* have supported real closures, just like C#. I am not aware of a technical reason not to. But they didn't, and the whole hoopla is about a very mild syntactic improvement, just as generics were.
PORTABLE java apps with font antialiasing and native widgets just doesn't exist. You need SWT for that, which requires per-platform libraries.