How do I compile my groovy source code into java 1.8 bytecode?
I'm using Grails 2.5.4, Java 1.8.0_74
I might be missing something obvious here, but the below settings in Grails BuildConfig.groovy don't seem to affect the Java bytecode being generated for Groovy source files.
Major version 49=Java 1.5, and 52=Java 1.8 (cite: how to check the jdk version used to compile a .class file)
grails.project.target.level = 1.8
grails.project.source.level = 1.8
Then to check bytecode version:
$ javap -verbose target/classes/MyGroovy.class | grep major
(standard input):7: major version: 49
$ javap -verbose target/classes/MyJava.class | grep major
(standard input):7: major version: 52
$ javap -verbose target/classes/UrlMappings.class | grep major
(standard input):7: major version: 49
$ javap -verbose target/classes/BootStrap.class | grep major
(standard input):7: major version: 49
So based on the above results, it seems that the target.level=bla configuration does affect Java source code, but not Groovy?
My test setup:
Vanilla grails 2.5.4 app: 'grails create-app foo'
Added one java source file, and one groovy. Placed in foo/src/*
Modified BuildConfig.groovy and set target/source levels to '1.8' instead of the default '1.6'
Those are all the steps. Totally simple.
My source code:
class MyJava {
String name;
int age;
public static String foo() { return "java!"; }
}
And...
class MyGroovy {
def name
def age
static foo() { 'groovy!' }
}
Related
I've prepared docker image that demonstrate the problem:
https://drive.google.com/uc?id=1i04_dVL0Rp5rxXCMuHaS4LYREkZjAAW1&export=download
This image is basically alpine:3.11 + apk add openjdk8 maven + my maven project containing sample minimal java class that shows problem
Which you can try with following commands:
# docker load -i bugexample.img
# docker run -w /root/bug-example --name bugtest bugexample /bin/ash build-until-sha-different.sh
If you are lucky enough (sometimes require several attempts) you will get following output:
Found! Sha1 of two subsequent otherwise identical builds are different!
--- 1.sha1
+++ 2.sha1
## -1,3 +1,3 ##
d8d46555c93da579adefc629f1764965a5493edb com/SimpleBug$1.class
75007242aab1e1877d24124d432cb246a79476a8 com/SimpleBug$SimpleBugBuilder.class
-23e8d0ea909b95a7955e0ec0adb4d12ae2193dd1 com/SimpleBug.class
+6a303d69d3f382b23ca04caee4102ee1cd7151e3 com/SimpleBug.class
The core issue with this build is that it produce different bytecode almost each time it get build even though nothing else (neither environment, nor code itself) had changed.
When I do compare these different class files I see that they differ in one single byte:
# cmp -lb 1_SimpleBug.class 2_SimpleBug.class
4053 66 6 65 5
Digging deeper into class file structure I've found that this difference come from stackmapframe constant pool pointers (StackMapTable attribute -> stack_map_frame entry with tag Object_variable_info -> cpool_index)
1_SimpleBug.class
#35 = Utf8 supSetStringParameter10
#36 = Utf8 Lcom/google/common/base/Supplier;
2_SimpleBug.class
#35 = Utf8 supSetStringParameter10
#36 = Utf8 Lcom/google/common/base/Supplier;
So one file points to #35 and another to #36. I don't think this is correct behavior.
I would like to sumbit this to a proper issue tracker but I don't know how to do that since all related JDK trackers are for devs only.
# java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (IcedTea 3.15.0) (Alpine 8.242.08-r0)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)
# mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /usr/share/java/maven-3
Java version: 1.8.0_242, vendor: IcedTea, runtime: /usr/lib/jvm/java-1.8-openjdk/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-1050-kvm", arch: "amd64", family: "unix"
And here is archive with java project:
https://drive.google.com/uc?id=1ZBdRzUk00QtpkGGnKAzipMjMtcnkKGN4&export=download
Well... The Mountain in Labour...
All of this was for nothing. Maven was main culprit. First time I ran my build it downloads lots of stuff that maven require (apart from my project dependencies) and then start compilation in same jvm. Second time build runs there is no need to download so compilation starts immediately. I don't know exactly why but first invocation of compiler is somehow affected by state of the jvm and this cause it to produce slightly different bytecode.
Solution was to add <fork>true<fork> to my pom.xml file and build now is totally reproducible... though takes ~2x more time :)
I still believe that this should not happen even if initial compilation happened inside maven jvm, and it may still be topic for improvement in javac but this "workaround" is acceptable.
I wanted to check out the mx image generator:
./mx image -cp $PWD/svmbuild -H:Class=HelloWorld -H:Name=helloworld
mx: unknown command 'image'
It seems that the "image" command is not available (anymore?)
Any replacement available?
Thanks
There's an mx native-image command.
The README file in the GraalVM project repository lists the following quick start snippet:
cd substratevm
mx build
echo "public class HelloWorld { public static void main(String[] args) {
System.out.println(\"Hello World\"); } }" > HelloWorld.java
$JAVA_HOME/bin/javac HelloWorld.java
mx native-image HelloWorld
./helloworld
Allegedly, one needs a JDK 8 with the JVMCI for this to work, here's a relevant quote from the README:
Install mx and point JAVA_HOME to a labsjdk.
For compilation native-image depends on the local toolchain, so make
sure: glibc-devel, zlib-devel (header files for the C library and
zlib) and gcc are available on your system.
This is my first time to try maven. My os in linuxmint.I have install maven successful.
mvn -v
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00)
Maven home: /home/gzx/danale/environment/apache-maven-3.3.9
Java version: 1.8.0_111, vendor: Oracle Corporation
Java home: /usr/java/jdk1.8.0_111/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "4.4.0-53-generic", arch: "amd64", family: "unix"
But when I have used mvn archetype:create
mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 -DartifactId=simple -DpackageName=org.sonatype.mavenbook
it showed a strange error.
[WARNING] Error injecting: org.sonatype.plexus.components.cipher.DefaultPlexusCipher
com.google.inject.ProvisionException: Unable to provision, see the following errors:Error injecting constructor, org.sonatype.plexus.components.cipher.PlexusCipherException: java.security.NoSuchAlgorithmException: SHA-256 MessageDigest not available
at org.sonatype.plexus.components.cipher.DefaultPlexusCipher.(Unknown Source)
while locating org.sonatype.plexus.components.cipher.DefaultPlexusCipher
It was so strange, how should I do?
I think maybe you have already figured your problem. But I got this bug yesterday and I fixed it today. I should write my solution down. Maybe someone will fall this trap.
Actually this problem is because Java cannot find the class "SHA-256 MessageDigest". But it is provided by JRE default. It should be found automatically.
If you access your JAVA_HOME, you may find a file whose name is jsse.pack in JAVA_HOME/jre/lib, and there is not a file named jsse.jar. That is the problem. Type
unpack200 jsse.pack jsse.jar
(unpack200 will be recognized as soon as you have set your Java path)
and the problem should be soloved.
Note:
Some JDK's have jsse.rar not jsse.pack, therefore, running "unpack200 jsse.rar jsse.jar" command will get the desired result, and will not delete the "jsse.rar" file (in case of *.pack files, they get replaced by the *.jar files).
The project has the following structure:
M
+---A
+---B
| +---B1
| +---B2
|
+---C
+---D
Every folder (M,A,B,B1,B2,C,D) contains a pom.xml file.
The pom.xml file from B1 contains the following lines:
<configuration>
<filters>
<filter>B/B1/PATH_TO_FILE_X</filter>
</filters>
</configuration>
Running
mvn clean install -Px -Dy -X
from the M folder:
using assembly plugin 2.4, everything works fine. It looks for path\M\B\B1\PATH_FO_FILE_X and it exists. (absolute path = project path + specified path)
using assembly plugin 2.4.1 (or 2.5.3), the file is not found. It looks for path\M\B\B1\B\B1\PATH_TO_FILE_X and there is a java.io.FileNotFoundException. (absolute path = submodule path + specified path)
I can manually change every path that cannot be resolved, but it's too risky because some paths can be resolved in a wrong way. If there is B\B1\PATH_TO_ANOTHER_FILE_X in B\B1\ it could cause problems.
Is there a generic method to solve this problem (keeping backward compatibility from 2.4 to 2.4.1)?
Details:
Maven 3.2.1
Java 7
Windows 7
Update:
It seems to be related to maven-filtering 1.2 that was introduced in 2.4.1:
http://maven.40175.n5.nabble.com/Apache-Maven-Assembly-Plugin-Version-2-4-1-Released-td5801647.html
https://jira.codehaus.org/browse/MASSEMBLY-686
https://jira.codehaus.org/browse/MSHARED-161
http://jira.codehaus.org/browse/MWAR-301
http://mail-archives.apache.org/mod_mbox/maven-announce/201211.mbox/%3C1791127681.01353276825400.JavaMail.Dennis#Dennis-Dator%3E
The following line from 2.4:
<mavenFilteringVersion>1.1</mavenFilteringVersion>
was replaced by
<mavenFilteringVersion>1.2</mavenFilteringVersion>
in 2.4.1.
Please note: Although this question involves a lib called Apache Camel I really think this is just a question about how modern Grails plugins work.
I am on Grails 2.4.2 here, and I am trying to use Apache Camel with Grails and found the Grails Routing plugin annd cannot even get it to install.
The directions say to install by issuing a grails install-plugin routing. When I do this I get:
grails install-plugin routing
Starting process on LT-IE-ZH/10.10.99.14
Loading Grails 2.4.2
|Configuring classpath
.
|Environment set to development
......Warning
|
Since Grails 2.3, it is no longer possible to install plugins using the install-plugin command.
Plugins must be declared in the grails-app/conf/BuildConfig.groovy file.
Example:
grails.project.dependency.resolution = {
...
plugins {
compile ":routing:1.3.2"
}
}
So I modify my BuildConfig.groovy like so:
plugins {
// plugins for the build system only
build ":tomcat:7.0.54"
compile ":routing:1.3.2"
...lots of other stuff omitted for brevity
}
Then the plugin says to create routes, issue a grails create-route <RouteName>. So I do exactly that:
grails create-route OrderListener
Starting process on LT-IE-ZH/10.10.99.14
Loading Grails 2.4.2
|Configuring classpath
|Running pre-compiled script
|Script 'CreateRoute' not found, did you mean:
1) CreateFilters
2) CreatePom
3) CreateApp_
4) CreateController
5) CreateHibernateCfgXml
Please make a selection or enter Q to quit:
What is going on here?!? How do I install/use this plugin?!? Am I losing my mind, or does this plugin simply not work?
Update
I run grails clean-all, then grails refresh-dependencies then grails create-route OrderListener and I get:
Loading Grails 2.4.2
.
|Environment set to development
.....Error
|
groovy.lang.MissingMethodException: No signature of method: CreateRoute.createArtifact() is applicable for argument types: () values: []
Error |
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
Error |
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
Error |
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
Error |
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
Error |
<huge stacktrace omitted>
Error |
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:207)
Error |
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:68)
Error |
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
Error |
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
Error |
... 68 more
Whenever you make a change in BuildConfig.groovy be sure to run grails compile to trigger dependency resolution, which will download new and updated plugins and jars, and it will also compile your code which helps to ensure that things are minimally compatible at least.
But the core issue here is that the plugin's CreateRoute.groovy script is badly broken. It's missing an important include and doesn't come close to calling createArtifact correctly. As a workaround until the authors get this fixed, create a script in your app's scripts folder called CreateCamelRoute.groovy with this content:
includeTargets << grailsScript('_GrailsCreateArtifacts')
target(createCamelRoute: "Creates a new Camel Route.") {
createArtifact(type: 'Route', path: 'grails-app/routes', name: argsMap.params?.get(0) ?: 'Example', suffix: 'Route')
}
setDefaultTarget(createCamelRoute)
It's intentionally named differently from the original because if Grails finds two with the same name it asks which one to use. This way you can just run
grails create-camel-route com.foo.bar.OrderListener
and it will work. Note that I changed the example a bit to include a package - always use packages :)