This blog has a new home! Please update your bookmarks to point to https://omairmajid.com
I will keep this current site around, but it will not be getting any new content. For new content, please go to the new site.
See you around!
This blog has a new home! Please update your bookmarks to point to https://omairmajid.com
I will keep this current site around, but it will not be getting any new content. For new content, please go to the new site.
See you around!
This post covers the versions and components in .NET Core 1.x.
.NET Core consists of multiple components that are each versioned
independently and can often be mixed and matched.
System.Runtime
, System.Theading
and so on. The source code for CoreFX is available at https://github.com/dotnet/corefx.dotnet
command and is responsible for deciding what happens next. The source for this is available at https://github.com/dotnet/core-setup.dotnet
subcommands) and their implementations that deal with building code. This includes handling the restoring of dependencies, compiling code, building binaries, producing packages and publishing standalone or framework dependent packages. The SDK itself consists of the CLI, which handles command line operations (at https://github.com/dotnet/cli) and various subprojects that implement the various operations the CLI needs to do.Each of the components listed above are versioned separately. You can find out the version of each of those components.
--version
option to dotnet
to see the version. For example:
$ ~/dotnet-1.1.1/dotnet --version 1.0.0-preview2-1-003176
dotnet
by itself without any arguments or options to see the version.
$ ~/dotnet-1.1.1/dotnet Microsoft .NET Core Shared Framework Host Version : 1.1.0 Build : 362e48a95c86b40cd1f2ef3d08741f7fed897956 Usage: dotnet [common-options] [[options] path-to-application] ...
ls /path/to/where/you/installed/dotnet/shared/Microsoft.NETCore.App
which relies on internal implementation details. For example:
$ ls ~/dotnet-1.1.1/shared/Microsoft.NETCore.App/ 1.1.1
Various official and unoffical packages, tarballs, zips and installers for .NET Core (including those available on https://dot.net/core) provide .NET Core in many variants. Two common ones are .NET Core SDK and .NET Core Runtimes. Each .NET Core SDK or .NET Core Runtime distribution contains a number (possibly 0) of hosts, sdk and shared framework components described above.
It’s possible to have multiple .NET Core SDKs and .NET Core Runtimes available on disk. You can select the versions easily.
To select the version of the SDK to use, use global.json
.
To select the version of the shared framework to use, use the .csproj
file (or project.json
if you are still using that).
Looking to try out OpenJDK 9? If you didn’t know, OpenJDK 9 is going to be the reference implemtation for Java 9 (assuming the pattern for Java 7 and Java 8 continues). Pre-release packages for Fedora 23, 24, 25 and Rawhide as well as RHEL 7 are available on copr:
https://copr.fedoraproject.org/coprs/omajid/openjdk9/
Please note that these are not official Fedora (or RHEL) packages. Official Fedora packages will be proposed and added to Fedora closer to OpenJDK 9’s release.
To install on Fedora:
# dnf copr enable omajid/openjdk9 # dnf install java-9-openjdk-devel
To install on RHEL (or CentOS) 7:
$ wget https://copr.fedorainfracloud.org/coprs/omajid/openjdk9/repo/epel-7/omajid-openjdk9-epel-7.repo $ su - # cp omajid-openjdk9-epel-7.repo /etc/yum.repos.d/ # yum install java-9-openjdk-devel
Then use as follows:
$ /usr/lib/jvm/java-1.9.0-openjdk/bin/java -version
To make it the default Java version, use update-alternatives.
# update-alternatives --config java # update-alternatives --config javac
If you are a user, making 9 the default may not be a great idea – OpenJDK 9 is in heavy development and lots of things are changing. There are also some known compatibility issues. On the other hand, if you are a Java developer, this will give you a good idea of how prepared your favourite libraries and tools are for Java 9.
Inspired by this post by Mark Wielaard I started wondering how OpenJDK 9 would fare in a -Wmisleading-indentation
test. So I built OpenJDK 9 using -Wall
to find out.
First, though, a big heads up: the OpenJDK 9 build selectively enables and disables warnings and turns on -Werorr
. There doesn’t seem to be a straight-forward way of enabling all compiler warnings everywhere. I ended up patching various makefiles to comment out various DISABLED_WARNINGS* f
lags. Hotspot needed a separate patch to initialize WARNING_FLAGS
with -Wall
in hotspot/make/linux/makefiles/gcc.make
. Then I built OpenJDK 9 using:
mkdir build cd build bash ../configure --with-extra-cflags="-Wall -Wextra" --with-extra-cxxflags="-Wall -Wextra -fpermissive" --disable-warnings-as-errors
A grep misleading-indentation build.log
was surprising:
jdk9-dev/jdk/src/java.base/share/native/libfdlibm/e_asin.c:103:17: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.base/share/native/libfdlibm/k_rem_pio2.c:201:61: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmscgats.c:613:13: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmscgats.c:690:13: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c:959:29: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmsintrp.c:1023:29: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmsio1.c:717:9: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmsopt.c:557:13: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmsopt.c:1021:29: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmsps2.c:1015:9: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmstypes.c:2398:9: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmstypes.c:2679:9: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/liblcms/cmswtpnt.c:109:9: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/libfontmanager/layout/SunLayoutEngine.cpp:154:25: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c:3880:16: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] jdk9-dev/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c:3997:10: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation]
libfdlibm
, liblcms
and libpng
are all external libraries that are bundled with OpenJDK. In the case of Linux distributions, they are often replaced with dynamically linked system libraries. That only code that’s actually part of OpenJDK itself is libfontmanager
.
Let’s take a look at that. The warning itself is:
/home/omajid/jdk9-dev/jdk/src/java.desktop/share/native/libfontmanager/layout/SunLayoutEngine.cpp:154:25: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] if (min < 0) min = 0; if (max < min) max = min; /* defensive coding */ ^~ /home/omajid/jdk9-dev/jdk/src/java.desktop/share/native/libfontmanager/layout/SunLayoutEngine.cpp:154:3: note: ...this 'if' clause, but it is not if (min < 0) min = 0; if (max < min) max = min; /* defensive coding */ ^~
So gcc thinks the programmer meant to guard the second if
statement with the first but failed to do so. But a quick look at the code suggests that these are indeed two independent checks – one checks and fixes min
and the other fixes max
. The developer just tried to save whitespace and write them in one line. Definitely a false postive.
Anyway, I am impressed with OpenJDK’s code quality: gcc doesn’t find any actual misleading indentation issues in OpenJDK.
I posted 3 patches today
The first patch is for OpenJDK 9. It creates a hole that allows alternative plugin implementations to plug into (pardon the pun) OpenJDK and make use of existing plugin-specific classes in OpenJDK.
The second and third patches are for IcedTea-Web. They allow IcedTea-Web to (progressively) build against OpenJDK8 and OpenJDK9.
What does this mean? Soon we might actually be able to build and run IcedTea-Web against OpenJDK. Yes, an Open Source/Free Software plugin running on top of OpenJDK (without any custom patches). Of course, a lot of this is still up in the air. The OpenJDK folks might not accept the patch, though I am hopeful they will – it’s very small and conservative.
Fun times ahead!
On December 5, 2013, the OpenJDK6 b29 source bundle was published at https://java.net/projects/openjdk6/downloads/.
This is a security bugfix release that includes all the security patches since the b28 release. A complete list of changes is available too.
The test results were not ideal.
The TCK failed, with all issues again basically boiling down to limited cryptography support. There are patches available to fix this. As far as I can tell this is not a regression.
The jtreg tests did not pass cleanly either.
A special thanks to Andrew Hughes for backporting all the security fixes to OpenJDK6.
Onwards to B30!
On October 4, 2013, the OpenJDK6 b28 source bundle was published at https://java.net/projects/openjdk6/downloads/.
This includes all the security patches since the b27 release as well as a major version bump in hotspot to hs23. A complete list of changes is available too.
The test results were not ideal.
The TCK failed, with all issues basically boiling down to limited cryptography support. There are patches available to fix this. As far as I can tell this is not a regression.
The jtreg tests did not pass cleanly either. Most of the failures were caused by tests trying to access “javaweb.sfbay.sun.com”, which is not accessible (from outside Oracle?). Some issues were caused by tests having a @build
tag but no @run
tag (perhaps older jtreg versions were more lenient). Two new tests, introduced by the 2013-04-16 security update, java/beans/Introspector/7064279/Test7064279.java
and java/beans/Introspector/Test5102804.java
both failed.
A special thanks to Andrew Hughes for all his contributions (especially with the hotspot 23 backport) and to Pavel Tisnovsky for testing.
Onwards to B29!
Someone asked me earlier today about how to contribute patches to OpenJDK. OpenJDK is probably not the easiest upstream to contribute patches to – their patch approval system is a little different from most other projects. I have tried to summarize the basic steps here. Let me know in comments if anything is not clear.
The OpenJDK Developer’s Guide covers most of this, but some of it is in too much detail and some of it is outdated. The process I describe here is what I have seen others use and what I have been using myself.
The overall process for submitting patches to OpenJDK is:
As you can see, it’s not a very complicated process. Most of the delays in patch acceptance have been when the patch is non-trivial or has unexpected issues (even if those issues are known only Oracle-internal and can only be guessed by those of us outside) or someone sufficiently qualified to review the patch is not available.
One thing to note: Oracle requires signing a Contributor License Agreement before they will accept non-trivial patches.
The first thing to do if you want to send a fix upstream is to identify what Group or Project it is for. For this purpose, both groups and projects are more-or-less the same (groups are more general). They consist of a collection of people who care about something. For example, some folks care about the javac
compiler, some others cares about the build system and others that care about ports to different architectures. There is a list of these groups and projects available on the OpenJDK web page, on the left side.
Simply look through them and try to pick what you think is the best project or group for your fix. Some groups and projects are obvious: if you are fixing something in swing, that’s the Swing group. If you want to fix something in the ARMv8 port, that’s the aarch64 project. If you can’t find the best group, you can fall back to Core Libraries if it’s a patch for the standard java library (that is, a fix for a java.* or javax.* class) or you can fall back to Hotspot if it is a fix for hotspot.
Make a note of the mailing list(s) and repositories used by the group.
Don’t worry if you can’t find the ideal group, project or repository; someone will point you in the right direction in later on, but it may mean (slightly) more work later.
Since you are trying to submit a patch upstream, I will assume you already have a fix for it. The first thing you need to do is to get the latest OpenJDK code using the most appropriate repository. And then make your fix. Once you have built and tested your fix, you can generate a patch for review. OpenJDK uses a custom tool called webrev to generate easier-to-reivew patches.
Assuming you are making a fix to hotspot, use it like so:
cd jdk8/hotspot ksh ../make/scripts/webrev.ksh
This program will look for changes in the current repository and generate a bunch of files. You should see a new
webrev.zip file and a webrev directory. The webrev directory should contain an index.html file that should look roughly like this existing one
Upload the webrev directory somewhere publicly where anyone who wants to review the patch can see it. A public dropbox folder works just fine, as done any personal webspace that you may have. Regular contributors to OpenJDK generally use cr.openjdk.java.net.
Now you need to send an email describing the patch and what it’s fixing to the right OpenJDK mailing list. remember to subscribe to the mailing list first, though.
Use a descriptive subject in the email, prefixing it with “RFR” (or Request for Review). Link to the public webrev in the email.
Hopefully, someone will review the patch quickly (depending on the fix, you may get a response within the hour or it may take a few days).
The reviewer may suggest improvements or additional fixes. They may also request additional cleanup or testing as well.
Once upstream is happy with the patch, a sponsor will ask you for a changeset that they can push or perhaps they will generate one for you. The details of producing a changeset are available in the developer’s guide. Since you don’t have push access, a sponsor will push the fix on your behalf to the appropriate repository. It will probably take a few weeks until that change makes it from group repository to integration repository to the master repository (jdk8/jdk8).
And that’s it! So don’t be afraid to propose patches for OpenJDK 🙂
Complete details about all this process is available, of course, in the Developer’s Guide.
I have always been impressed by the effort OpenJDK folks go to maintain API compatibility. I recently came across a nifty little trick that is used in the OpenJDK codebase to help achieve this goal. Behold the SharedSecrets class! The name of the class is a little misleading since it doesn’t have anything to do with the cryptographic concepts of shared secrets. The javadocs do a (slightly) better job describing its purpose:
/** A repository of "shared secrets", which are a mechanism for calling implementation-private methods in another package without using reflection. A package-private class implements a public interface and provides the ability to call package-private methods within that package; the object implementing that interface is provided through a third package to which access is restricted. This framework avoids the primary disadvantage of using reflection for this purpose, namely the loss of compile-time checking. */
In other words, it is used to make private methods public, without using reflection! AND it works under a security manager! At first, I thought this was too good to be true but it turns out that the concept behind it is pretty simple. Here’s how it works. Suppose we have a class with a fixed public api and we wish to add a new method to it that we would like to be able to use internally within the project but not provide as an api:
public class FixedPublicApi { private static doFoo() { /* do something */ } }
We could choose to add the doFoo method to another class (in fact, it will primarily be accessed through another class) and make it public, but let’s assume that the only way to avoid duplicating lots of code is to keep doFoo in FixedPublicApi. First we create an interface that exposes the method we want to be invoked:
public interface FooHandler { public void doFoo(); }
Then we modify the SharedSecrets class (or it’s equivalent in our codebase), to set the implementation for FooHandler
public class SharedSecrets { private static FooHandler fooHandler; public static void setFoo(FooHandler handler) { fooHandler = handler; } public static void foo() { fooHandler.doFoo(); } }
Finally we modify the FixedPublicApi class to install a handler:
public class FixedPublicApi { static { SharedSecrets.setFoo(new FooHandler() { public void doFoo() { FixedPublicApi.doFoo(); } } } private static doFoo() { /* do something */ } }
And that’s it! Now we can use SharedSecrets to call the private method:
SharedSecrets.doFoo();
Hats off to whoever came up with this great technique.
I have been playing around with awesome and ran into some issues with Java programs (apparently others users are running into those problems too). I hacked together a patch against OpenJDK7 that seems to solve all my issues:
diff --git a/src/solaris/classes/sun/awt/X11/XWM.java b/src/solaris/classes/sun/awt/X11/XWM.java
--- a/src/solaris/classes/sun/awt/X11/XWM.java
+++ b/src/solaris/classes/sun/awt/X11/XWM.java
@@ -102,7 +102,8 @@
METACITY_WM = 11,
COMPIZ_WM = 12,
LG3D_WM = 13,
- CWM_WM = 14;
+ CWM_WM = 14,
+ AWESOME_WM = 15;
public String toString() {
switch (WMID) {
case NO_WM:
@@ -131,6 +132,8 @@
return "LookingGlass";
case CWM_WM:
return "CWM";
+ case AWESOME_WM:
+ return "awesomewm";
case UNDETERMINED_WM:
default:
return "Undetermined WM";
@@ -573,8 +576,12 @@
// getIntProperty(XToolkit.getDefaultRootWindow(), XAtom.XA_CARDINAL)) == 0);
}
+ static boolean isAwesomeWM() {
+ return isNetWMName("awesome");
+ }
+
static boolean isNonReparentingWM() {
- return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM);
+ return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM || XWM.getWMID() == XWM.AWESOME_WM);
}
/*
@@ -754,6 +761,8 @@
awt_wmgr = CWM_WM;
} else if (doIsIceWM && isIceWM()) {
awt_wmgr = XWM.ICE_WM;
+ } else if (isAwesomeWM()) {
+ awt_wmgr = XWM.AWESOME_WM;
}
/*
* We don't check for legacy WM when we already know that WM
Given the effort it’s taking to push a fix for mutter (the default gnome3 window manager), I wouldnt hold my breath waiting for this code to make it upstream.