I am working with ForgeGradle (Minecraft Forge modding platform).
I'd like to obfuscate my mod before publishing but the nature of Forge platform won't allow me to do it by simply running program like ProGuard after compilation (with defined libraries).
Why?
The structure goes like this:
Mod -> Forge -> Minecraft
Since Minecraft uses its own obfuscated classes and ForgeGradle compilator is not DIRECTLY obfuscating Mod's code to fit with Minecraft's one, it is not possible to use MC.jar as library while using ProGuard. Compiled Forge Mod is actually decoded by Forge in runtime using SRG names. The logic behind this is not easily explainable so I'll just note: I cannot obfuscate .jar in a way to fit with libraries.
So I though - I could just take my mod's code (.java files) and rename all fields/methods/classes that are MINE before Forge compilation.
Is there a software that would allow me to pick number of .java files and "obfuscate" them in a way to not reaname references that don't belong to them?
EDIT (more explanation):
Mod's code has 3 states: Development, Compiled, Running.
I will try to give an example:
Let's say there is a decompiled method ItemSword.onHit() inside Minecraft.jar
And its compiled (obfuscated) version look like this: bca.aa(), also all packages are lost (flattened).
In mod's development state of code (.java) to make reference to it we simply make: ItemSword.onHit()
When we compile mod the call will look like this (.class): ItemSword.func_ab4234() - this is the SRG I was talking about.
Now when the mod will be loaded to game, forge will translate "ItemSword" to "bca" and "func_ab4234()" to "aa()"
Because of this I can't even add proper library - there IS NONE. I will always get (in ProGuard) NoClassDefFound Warning and I can't ignore it (it will crash compilation).
So after this edit - Is it still possible to make obfuscation with ProGuard (considering I cannot have "good" library assigned)?
Did you try the proguard options?
http://proguard.sourceforge.net/manual/usage.html
e.g. for Serializable classes and other stuff put this to your proguard configuration (you also can preserve complete classes if you like):
<!-- With this code serializable classes will be backward compatible -->
<keepnames implements="java.io.Serializable"/>
<!-- or for native access:-->
<keepclasseswithmembernames>
<method access="native"/>
</keepclasseswithmembernames>
<!--Preserve all public classes, and their public and protected fields and methods.-->
<keep access="public">
<field access="public protected"/>
<method access="public protected"/>
</keep>
If I got your question, you want to obfuscate your own code, not anything beyond that. That's what ProGuard is actually quite good at. Let's assume you created your classes in the packages com.foo and com.bar. You can use this simple ProGuard command to only obfuscate your own classes:
-keep class !com.foo.**,!com.bar.** { *; }
It tells ProGuard to not obfuscate any members of classes which do not belong to either com.foo or com.bar.
If you are getting NoClassDef errors, you added the wrong library. I guess you are using some kind of IDE (perhaps eclipse). Have a look at the libraries your project references to find the correct library classpath (e.g. a jar file). You basically need to find the classpath used for compiling your code, ProGuard will take that as well and everything should work.
Related
Motivation:
In our code we have a few places where some methods are run by their name. There are some big if-else-if blocks with each function name and call of the corresponding method (I use the term function to describe just names, for example function X01 might correspond to method SomeClass.functionX01). I've been looking into ways to improve that
Goal:
Write just methods that are annotated with some custom annotation, removing the need to update or even include if-else-if blocks in order to run specific function. Have access to any generated code if any code is generated.
What I did:
I've created first prove of concept using runtime annotations and it proved successful, but slower then if-else-if. Next attempt was with source annotation
I've followed this link for an example, however it did not seam to run in IntelliJ. What I wanted is to have - in this case PersonBuilder class generated, instead there was none. In some cases an error was raised Error:java: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider BuilderProcessor not found
After some Googling and failing to find anything I've turned to book (Core Java, Volume II - Advanced Features - 9th Edition, Polish translation) and there was reccomended to run the following commands:
javac [AbstractProcessor implementation]
javac -processor [Compiled Processor] [other source files to compile]
This worked, however is unsatisfactory as it needs to happen inside IDE (NetBeans and IntelliJ to be specific) automatically during build. Code does not need to be generated on the fly, but programmer must have access to it after build (as in - be able to call methods of generated classes)
Question:
How to have and use generated code used in NetBeans and IntelliJ without the need of using external tools? Is it possible, or using reflection, runtime annotations or external tools is the only way?
Additional info (just in case):
Language level: Java 1.8
JVM versions: 12 and 13
IDEs: NetBeans and IntelliJ
I would like to get deeper understanding on how Java deals with different versions of Classes/Packages/etc., but couldn't find any resources or at least the best way to google for it. The problem is as follows.
Imagine we have some external package com.external.package that contains a definition of SomeInterface.
Now I write a java class MyClass that implements SomeInterface, and using com.external.package v1.0.0. Next I package a (lean) jar containing MyClass.
Now I plug this jar in another program that is looking for implementations of SomeInterface, but in it's dependencies, it is using com.external.package v2.0.0.
Is the reason I get Failed to find any class that implements SomeInterface that versions of SomeInterface don't match in the program and in the jar that contains a class extending it?
Basically the question I would like to find an answer for is what info do jars store regarding external dependencies? Does it store the exact versions of them and if they don't match at the runtime it complains? But why does it even allow running the program with references to same dependency, but different versions?
Is the reason I get Failed to find any class that implements SomeInterface that versions of SomeInterface don't match in the program and in the jar that contains a class extending it?
There is no "versioning" happening here. Simply, the error states no such class exists on the classpath. For example, you didn't put a -cp in your java command to add that extra JAR/class file.
Other reasons this could happen is that an API marks a class as deprecated in v1, then decides to remove it from v2. In which case, you best try to compile and test your code against the proper library versions before you package your own code. If you made an uber JAR, the classes should get shaded, and you probably wouldn't have missing classes.
Maven projects do have the concept of transitive, versioned dependencies, but you've not said anything about that
Seeing that the original question has found an answer already, it seems somewhat relevant to mention that Java Packages and JARs could be used for specifying package version information as discussed in the following documentation:
https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp89936
Also, the Oracle Java Tutorials discuss them and further concepts around deployment of programs as JAR Files as documented here:
https://docs.oracle.com/javase/tutorial/deployment/jar/index.html
I am somewhat new to RubyMine but here is my problem. I have a JRUBY Class that I want to extend from a Java class. My Java class is part of a submodule I have imported using git. This is my project structure:
src --> Submodule --> <Directories> --> ClassIWantToExtend.java
--> Ruby Code --> <Directories> --> JRubyClassThatExtendsJava.rb
However, when using RubyMine I have been unable to figure out how to extend this Java class. It can't seem to find it. My current class is blank. This is all I have:
require 'java'
class JRubyClassThatExtendsJava
end
I have tried using '<' and 'include' but when autofilling RubyMine can't seem to find my Java Class. I did just add the submodule using a CLI Git Command. Is it possible I have to add something for RubyMine to see it?
Thanks for any help in advance.
RubyMine, as far as I know (bought a license but never actually used it due this) does not include support for .java (not even a syntax highlighter) - the motivation seems to be that they have a separate product that is a Java IDE. thus this answer is not going to be RubyMine specific :
first you'll need to compile the .java sources and either pack them in a .jar or simply keep in mind what directory the .class files are (javac -d OUT_DIR)
than in your .rb you can either require 'path/to/packed.jar' or simply $CLASSPATH << 'path/to/classes/OUT_DIR'
... than you should be able to load the Java class and extend it in Ruby
I'm getting desperate with this Problem: I want to export/run my Android Application with one additional .jar I added to the buildpath. I'm sure I added it correctly, there are 5 other .jars included and they all work fine.
with this special one I get the mentioned error.
I've already tried everything that can be found in this question:
"Conversion to Dalvik format failed with error 1" on external JAR
and several other links google spat out. The main Problem is, I actually do not understand what the message I appended want's to tell me because if I add all the jars to a "normal" javaproject, it runs perfectly fine...
Developing on Android 4.0.3,
proguard 4.8,
adt 16.0.1.v201112150204-238534,
eclipse 3.7.1.r37
please help me
[2012-07-18 10:45:48 - myapp] Dx warning: Ignoring InnerClasses attribute for an anonymous inner
class (iaik.xml.crypto.XSecProvider$1) that doesn't come with an
associated EnclosingMethod attribute. This class was probably produced
by a compiler that did not target the modern .class file format. The
recommended solution is to recompile the class from source, using an
up-to-date compiler and without specifying any "-target" type options.
The consequence of ignoring this warning is that reflective operations
on this class will incorrectly indicate that it is not an inner
class.
...
...
[2012-07-18 10:45:48 - myapp] Dx warning: Ignoring InnerClasses attribute for an anonymous inner
class (iaik.xml.crypto.XSecProvider$2) that doesn't come with an
associated EnclosingMethod attribute. This class was probably produced
by a compiler that did not target the modern .class file format. The
recommended solution is to recompile the class from source, using an
up-to-date compiler and without specifying any "-target" type options.
The consequence of ignoring this warning is that reflective operations
on this class will incorrectly indicate that it is not an inner
class.
Ill-advised or mistaken usage of a core class (java.* or javax.*) when
not building a core library.
This is often due to inadvertently including a core library file in
your application's project, when using an IDE (such as Eclipse). If
you are sure you're not intentionally defining a core class, then this
is the most likely explanation of what's going on.
However, you might actually be trying to define a class in a core
namespace, the source of which you may have taken, for example, from a
non-Android virtual machine project. This will most assuredly not
work. At a minimum, it jeopardizes the compatibility of your app with
future versions of the platform. It is also often of questionable
legality.
If you really intend to build a core library -- which is only
appropriate as part of creating a full virtual machine distribution,
as opposed to compiling an application -- then use the
"--core-library" option to suppress this error message.
If you go ahead and use "--core-library" but are in fact building an
application, then be forewarned that your application will still fail
to build or run, at some point. Please be prepared for angry customers
who find, for example, that your application ceases to function once
they upgrade their operating system. You will be to blame for this
problem.
If you are legitimately using some code that happens to be in a core
package, then the easiest safe alternative you have is to repackage
that code. That is, move the classes in question into your own package
namespace. This means that they will never be in conflict with core
system classes. JarJar is a tool that may help you in this endeavor.
If you find that you cannot do this, then that is an indication that
the path you are on will ultimately lead to pain, suffering, grief,
and lamentation.
[2012-07-18 10:45:48 - myapp] Dx 1 error; aborting
[2012-07-18 10:45:48 - myapp] Conversion to Dalvik format
failed with error 1
This is how my project looks int he explorer:
The problem is that the jar you are including has a class in the java.* or javax.* namespace. dx does not allow this, as mentioned in the last big error message.
If you actually need these classes, you'll need to move them to a different package, using something like the jarjar tool. Otherwise, you'll need to remove them from the jar -- it may be possible to have proguard to remove them before everything gets dx'd, I'm not sure.
I faced the same problem, I finally resolved it by exporting my private library explicitly.
Like:
Project >> properties >> Java Build Path >> Libraries >> Add External Jars.
Note: Removed my all private libraries from libs folder. I know it is not correct but it worked for me.
Thanks,
Anil
Do as follows :
project
> properties
> java build path
> libraries
> remove all including android jars
Now, go the project browser, right click on the project you are working on, then
android tools
> fix project properties.
Do a clean and then build.
Just restart eclipse, and the error won't occur anymore
If you work on Win7 change this line:
call %java_exe% -jar "%PROGUARD_HOME%"\lib\proguard.jar %*
in proguard.bat file to this:
call %java_exe% -jar "%PROGUARD_HOME%"\lib\proguard.jar %1 %2 %3 %4 %5 %6 %7 %8 %9
proguard.bat is in:
[Android SDK Installation Directory]\tools\proguard\bin\proguard.bat
Edit:
I hope a combine of these help you:
1-Try to delete libraries projects from your project.
2-Try to export your project(as archive file),delete project and it's source from workspace and then import it again.
3-Try to remove your jars from path,do clean-build and then add them again to your project.
I had the same error when using my own obfuscated lib jar.
my log:
warning:Ignoring InnerClasses attribute for an anonymous inner class that doesn't come with an associated EnclosingMethod attribte.This class was probably prouduced by a compiler that did not target the morden .class file format...
And I solved it like this:before I obfuscate my jar,I added "-keepattributes EnclosingMethod" to the proguard.cfg(or proguard-project.txt in latest android adt version).
Agree with hasanghaforian. The easiest solution is to remove libraries project.
Right click your project->Properties->Java Build Path then remove Library Projects
There is a java file, which has some dependencies jars. But now, I don't have those jars, and I have to compile it to a .class file.
Is it possible to do this?
UPDATE
Thanks for your answers.
At first, I thought we can create some stubs for the missing dependencies, that's easy but boring. Since we can create the stubs without missing stubs to make the compiler happy, why can't we make a tool do it automatically? The tool doesn't need to create stubs, but reads the java file, collects informations, and then builds the .class files.
But if the "import" statements in the java file contain "*", that will be a problem:
import aaa.*
import bbb.*
public class Hello {
World world;
}
We don't know if the class "World" is under package "aaa" or "bbb". If we are not familiar with the missing dependencies, we even don't know how to create a stub for the class "World".
But if the "import" statements are clear, I think it's possible, but maybe no one will write such a tool
You could go crazy and hand craft the required dependencies as stubs that do nothing except keep the compiler happy.
No. Sorry. You'll need all dependncies in the classpath to compile.
No. But you could provide stubbed-out versions of the dependency class files, if it is only a handful of classes that the code your are trying to compile uses directly.
Then in theory if you take the .class file that compiles and place the real dependencies on the classpath with it your app will work using the correct (non-stubbed-out) dependency classes.
Before any file is compiled it always looks up for any dependencies.
but you said you dont have those jars!!!
see if you can remove the dependencies relation for that project/file and then try to compile it. give it a try!