How to Obfuscate a fatJar with Klassmaster - java

I have a fat jar which is generated by using gradle script. Post the gradle script when I run the following command :-
java -jar fileName.jar
it is running the main method and things are fine. Nevertheless when I try to obfuscate this jar, the resulting jar is complaining that :-
Error: Invalid or corrupt jarfile ObfusactedTest.jar
My code is as follows:-
build.gradle:-
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath files("E:\\softs\\ZKM\\ZKMEval\\ZKM.jar") //ZKM_JAR_PATH must be set to point to your ZKM.jar
classpath 'com.zelix.gradle:plugin:1.0.0'
}
}
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'com.zelix.gradle.plugin'
group = 'com.github.jitpack'
sourceCompatibility = 1.8 // java 8
targetCompatibility = 1.8
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.11'
compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.4'
}
jar {
manifest {
attributes "Main-Class": "com.github.jitpack.Hello"
}
zip64 = true
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
zkmSetting {
scriptName = "Obfuscate.txt" //Must be set to point to the ZKM Script to execute.
}
Obfuscate.txt:-
print "Obfuscating fatJar.....";
classpath
"C:\Program Files\Java\jdk-10.0.2\lib\jrt-fs.jar"
".\obfuscateFatJar.jar";
open ".\obfuscateFatJar.jar" {"*.class"};
exclude org.apache.commons.*.*;
exclude com.github.jitpack.Hello.*;
obfuscate keepInnerClassInfo=false
keepGenericsInfo=true
exceptionObfuscation=heavy
encryptStringLiterals=flowObfuscate;
saveAll archiveCompression=asIs
deleteEmptyDirectories=true
deleteXMLComments=false
"ObfusactedTest.jar";
By the way Hello.java has got the main method.

Your ZKM Script "open" statement specifies the {"*.class"} file filter. So you are filtering out ALL non-class files including your MANIFEST.MF. See https://www.zelix.com/klassmaster/docs/openStatement.html#filter.
A missing MANIFEST.MF will give you a "Invalid or corrupt jarfile" error. Note that your Zelix KlassMaster log file will contain messages like the following.
MESSAGE: Filtering out path 'obfuscateFatJar.jar!META-INF/MANIFEST.MF' because it does not match specified filter '{".class"}>' (D)*
You can work around this by not using a file filter (the safest option in this case) or by broadening your file filter to include other file types. E.g. {".class" || ".MF"}

Update the filter in the class path. The code looks like this now. Works like a charm.
execute "del ObfusactedTest.jar";
classpath
"C:\Program Files\Java\jdk-10.0.2\lib\jrt-fs.jar"
".\obfuscateFatJar.jar";
open ".\obfuscateFatJar.jar" {"*.class" || "*.MF"};
exclude org.apache.commons.*.*;
obfuscate keepInnerClassInfo=false
keepGenericsInfo=true
exceptionObfuscation=heavy
encryptStringLiterals=flowObfuscate;
saveAll archiveCompression=asIs
deleteEmptyDirectories=true
deleteXMLComments=false
"ObfusactedTest.jar";

Related

Trying to use tools.jar - gradle

I am using gradle to package some java code into a jar. I am using some classes from tools.jar. I have had success in gradle building it and making a jar, but when I run that jar using java -jar <package>.jar I get the folowing
java.lang.NoClassDefFoundError: com/sun/tools/attach/VirtualMachine.
Since tools.jar is something you get with a jdk, not a jre. Is there a way I can bundle tools.jar with my package.jar and have my jar work anywhere?
Here is my build.gradle so far.
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
}
description = "A java program"
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
flatDir {
dirs System.properties['java.home'] + '/../lib'
}
}
jar {
archiveName = "jProg.jar"
manifest {
attributes(
'Dependencies': 'com.sun.tools'
)
}
}
dependencies {
compile group: 'com.sun', name: 'tools'
}
Probably what you need is called 'fat jar' (Gradle packs all dependencies to single jar)

Gradle building old version of code

I'm trying to build a fat jar with gradle but every time I do I get a really old version of the program. Running the program from main directly in IntelliJ works fine so it is something with the gradle build itself that is not working. When i check the jar in (project path)/build/libs the date and time of the file has changed so it did indeed build but when i start it i get a month old build. I suspect there might be some cache that is causing this but i do not know where that is located.
build.gradle
version '1.0.2'
apply plugin: 'java'
repositories {
mavenCentral()
}
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Example',
'Implementation-Version': version,
'Main-Class': 'com.example.Main'
}
baseName = project.name
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
jar {
manifest {
attributes(
'Main-Class': 'com.example.Main',
)
}
}
dependencies {
compile 'com.intellij:forms_rt:6.0.5'
compile project(':common')
testCompile group: 'junit', name: 'junit', version: '4.11'
sourceCompatibility = 1.7
targetCompatibility = 1.7
}
settings.gradle
rootProject.name = 'example'
include ':common'
project(':common').projectDir = new File(settingsDir, '../common')
Command
./gradlew fatjar
Well, I discovered the problem and it was a combination of things. The only thing that was actually outdated was the form ui. The reason for this was that IntelliJ started using binary class files for the forms instead of java source files.
To fix it go to settings then editor and after that GUI designer. Press Java source code instead of binary class files. Regenerate the design (might have to delete the generated code and run it again). Then build it with gradle, it should now work.

Fat jar built with Gradle doesn't include libraries

I'm trying to build a fat jar which would contain all .jar libraries included in 'libraries' folder.
Here is a snapshot of my build.gradle file:
group 'MyApp'
version '2.0'
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile files('libraries/ojdbc7.jar')
compile files('libraries/postgresql-42.1.4.jar')
compile files('libraries/db2jcc.jar')
}
tasks.withType(Jar) {
destinationDir = file("$rootDir/target")
}
jar {
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'MainLauncher'
}
processResources{
exclude '*'
}
archiveName 'myapp.jar'
}
All .jar libraries are included into 'libraries' folder located in root of the project.
For some reason my code works fine in IDE, however fails to execute some tasks when run as a standalone .jar file.
When I decompress the jar, I can see all content inside root folder including libraries which fail to be found.
Is there anything I'm doing wrong?

using Kotlin with Gradle

I'm new to Kotlin and Gradle, and tried to follow these steps, so I got the following 2 files:
after running gradle init I changed the build.gradle to be:
// set up the kotlin-gradle plugin
buildscript {
ext.kotlin_version = '1.1.2-2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// apply the kotlin-gradle plugin
apply plugin: "kotlin"
apply plugin: 'application'
mainClassName = "hello.main"
// add kotlin-stdlib dependencies.
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
Hello.kt:
package hello
fun main(args: Array<String>) {
println("Hello World!")
}
Then I run the gradle build and got the build\classes\main\hello\HelloKt.class
my question is: Why the file generated is .class not .jar and how to get the .jar file and how to run it, I tried running the generated file using kotlin -classpath HelloKt.class main but got an error error: could not find or load main class hello.main
The classes are the direct output of the Kotlin compiler, and they should be packaged into a JAR by Gradle afterwards. To build a JAR, you can run the jar task, just as you would in a Java project:
gradle jar
This task is usually run during gradle build as well, due to the task dependencies.
This will pack the Kotlin classes into a JAR archive (together with other JVM classes, if you have a multi-language project), normally located at build/libs/yourProjectName.jar.
As to running the JAR, see this Q&A for a detailed explanation: (link)
Thanks for #hotkey answer, it helped me going the correct way.
First of all there is a mistake in the main class declaration, as it should follow the new methodology, that is in the below format:
mainClassName = '[your_namespace].[your_arctifact]Kt'
namespace = package name
arctifact = file name
so, considering the names given in the example above where filename is: Hello.kt, and the namespace is hello, then:
mainClassName = `[hello].[Hello]Kt`
using the previous method, that contains:
apply plugin: 'application'
mainClassName = 'hello.HelloKt'
the generated .jar file is not including the kotlin runtime, so the only way to execute it, is by:
d:/App/build/libs/kotlin -cp App.jar hello.HelloKt
but in order to generate a self contained jar that can be self-executed, and contains the kotlin runtime then the build.gradle should be written as:
// set up the kotlin-gradle plugin
buildscript {
ext.kotlin_version = '1.1.2-2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// apply the kotlin-gradle plugin
apply plugin: "kotlin"
// add kotlin-stdlib dependencies.
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
jar {
manifest {
//Define mainClassName as: '[your_namespace].[your_arctifact]Kt'
attributes 'Main-Class': 'hello.HelloKt'
}
// NEW LINE HERE !!!
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
followed by gradle build, the [your_working_folder].jar file will be generated at the build/libs folder, assuming the working folder name is app, then file app.jar will be generated.
To run this file, one of the following 2 commands can be used:
D:\App\build\libs\java -jar App.jar
OR
D:\App\build\libs\kotlin App.jar hello.HelloKt

Add to subproject to gradle jar

How can I add a subproject referenced using project(':api') to the jar gradle builds?
This is the build.gradle of my main project. The subproject is includes as git submodule and has a similar buildscript.
apply plugin: 'java'
sourceCompatibility = 1.5
version = '1.0'
jar {
manifest {
attributes('Main-Class': '..........')
}
}
repositories {
mavenCentral()
}
dependencies {
compile files('libs/jfxrt.jar')
compile project(':api')
testCompile group: 'junit', name: 'junit', version: '4.11'
}
I figured it out on my own.
Include the source of a subproject in the main jar:
sourceSets {
main {
java {
srcDir project(':api').file('src/main/java')
}
}
}
Including the classes of a jar in the main jar:
jar {
from zipTree('libs/abc.jar')
}
Try to add classpath to your manifest file. You need to have directory (example below uses "lib") to keep jar files on which your project depends.
Try modifying your "jar" block in gradle build to something like this. I have some addition properties just for demonstration. But the important one is Class-Path
jar {
manifest.attributes(
'Class-Path': lib/api.jar
'Built-By': System.getProperty('user.name'),
'Built-JDK': System.getProperty('java.version'),
'Built-OS': System.getProperty('os.name'),
'Built-DATE': buildDate,
)
}
I hope it helps to fix your issue.
In the simplest case, a fat Jar can be created as follows:
main/build.gradle:
jar {
from configurations.runtime
}
There are other, more robust solutions, such as the gradle-one-jar plugin for "main" method style applications.

Categories

Resources