When I run the following JUnit test, the memory of the java process is increasing constantly. After several hours, it uses more than 2go. However, when I look with jvisualvm, the heap and permgen size are stable, I don't see any leak. The test is run with -Xmx32m
public class TestCat {
public static class A { }
#Test
public void testCategory() {
for(;;) {
GroovyCategorySupport.use(A.class, new Closure<Object>(null) {
public Object call() { return null; }
});
}
}
}
I have tested it with Groovy 2.4.7, Windows and a JRE1.7_80, MacOS and JRE1.7_60.
I can't reproduce this bug with MacOS and JRE 1.8.0_91
I suppose it's related to a bug in the JRE1.7, and I am looking for a way to mitigate this issue:
my test is maybe wrong ? How is it possible to leak "system" memory without leaking heap space or permgen space ?
Is it a "known" bug or incompatibility between Groovy and a JRE 1.7 ?
How to use groovy category with a 1.7 jre and without suffering this memory leak ?
EDIT
I can reproduce this bug by calling VMPluginFactory.getPlugin().invalidateCallSites(), which translates with this "pure java" unit test :
public class TestSwitchPoint {
#Test
public void testSP() {
SwitchPoint switchPoint = new SwitchPoint();
for(;;) {
SwitchPoint old = switchPoint;
switchPoint = new SwitchPoint();
SwitchPoint.invalidateAll(new SwitchPoint[]{old});
}
}
}
In fact, only new SwitchPoint() is enough.
Yes, there is a bug in JRE. Native memory leak happens inside JVM at the following place:
(VM)
- os::malloc(unsigned long, unsigned short, unsigned char*)
- CHeapObj<(unsigned short)1792>::operator new(unsigned long, unsigned char*)
- JNIHandleBlock::allocate_block(Thread*)
- JNIHandleBlock::allocate_handle(oopDesc*)
- JNIHandles::make_weak_global(Handle)
- instanceKlass::add_member_name(int, Handle)
- MethodHandles::init_method_MemberName(Handle, methodOopDesc*, bool, KlassHandle)
- MethodHandles::init_method_MemberName(Handle, CallInfo&, Thread*)
- MethodHandles::resolve_MemberName(Handle, KlassHandle, Thread*)
- MHN_resolve_Mem
(JAVA)
- java.lang.invoke.MethodHandleNatives.resolve(MemberName, Class)
- java.lang.invoke.MemberName$Factory.resolve(byte, MemberName, Class)
- java.lang.invoke.MemberName$Factory.resolveOrNull(byte, MemberName, Class)
- java.lang.invoke.DirectMethodHandle.maybeRebind(Object)
- java.lang.invoke.DirectMethodHandle.bindReceiver(Object)
- java.lang.invoke.CallSite.makeDynamicInvoker()
- java.lang.invoke.MutableCallSite.dynamicInvoker()
- java.lang.invoke.SwitchPoint.<init>()
- Test.main(java.lang.String[])
It is a known issue with MemberNameTable: JDK-8152271. Unfortunately, it has been fixed only in JDK 9. By a lucky chance your problem is not seen on JDK 8 because of MethodHandles refactoring done in JDK-8050166. Although MemberNameTable probem remains, SwitchPoint() no longer creates new MemberNames. The latter fix was also backported to JDK 7u91.
Groovy runtime uses MethodHandles if it detects Java 7+. You may workaround this by patching VMPluginFactory to use Java 6 plugin. Here is the patch. If included in classpath before Groovy libraries, it will force Groovy runtime to use Java 6 - compatible VMPlugin.
So, you have the following options to workaround the memory leak:
use JRE 8 (recommended)
use JRE 7u91+
include VMPluginFactory patch in classpath
Related
I have a set of code procedures I use in a lot of places and I'm trying to basically move it to a library.
So I created my library with some unit test and everything was looking promising and at least working localy..
When I went to my project and deleted the files locally and then try to import them from my library as a dependency the code does not work.
I always get this kind of error
Class does not define or inherit an implementation of the resolved method abstract getProperty(Ljava/lang/String;)Ljava/lang/Object; of interface groovy.lang.GroovyObject.
I'm definitely not an expert on groovy but basically I use it in my Jenkins and Gradle for pipelines and some basic packaging or environment deployments.
I can show my class:
class ConsoleRow implements Comparable {
...
final Integer priority
final String rowStatus
final String message
final String rowReportClass
ConsoleRow(Integer priority, String status, String msg, String rowC) {
this.priority = priority
this.rowStatus = status
this.message = msg
this.rowReportClass = rowC
}
#Override
int compareTo(Object o) {
return this.priority <=> ((ConsoleRow) o).priority
}
The line that gives me the error is this actual compareTo when trying to do the "this.priority"
Caused by: java.lang.AbstractMethodError: Receiver class com.abc.insight.jenkins.ConsoleRow does not define or inherit an implementation of the resolved method abstract getProperty(Ljava/lang/String;)Ljava/lang/Object; of interface groovy.lang.GroovyObject.
at com.abc.insight.jenkins.ConsoleRow.compareTo(ConsoleRow.groovy:24)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder.processOutput(ConsoleOutputHtmlBuilder.groovy:115)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder.processOutput(ConsoleOutputHtmlBuilder.groovy)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder.buildReport(ConsoleOutputHtmlBuilder.groovy:20)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder$buildReport.call(Unknown Source)
at build_e548mc0tqjmi822clitlsycdk.runReport(C:\dev\repo\insight\insight-health-check\data-foundation\smoke-test\build.gradle:77)
The calling function is just trying to sort a list of those objects
List<ConsoleRow> outputRows = []
...
return outputRows.sort()
The part that gets me really confused is that if instead of importing the library as a dependency I just do this directly in this repo and put my sources in my buildSrc\src\main\groovy\com\abc\insight the code works fine...
So I really think it might be how I package and publish my library that might be wrong.
I'm really sure this is some basic error on my part because I never did a groovy library before but somehow I can't make it work.
It might be that my publication is just wrong, on my library side I'm using this plugins to do the publishing.
plugins {
id 'groovy'
id 'java-library'
id 'base'
}
publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
}
I tried to change components.groovy but somehow it does not work.
Any ideas or tips, I think my question probably is showing some really lack of know-how on groovy but looking at the documentation and examples I could not figure it out.
Doing some debug in my IDE the compareTo that generates the exception looks like this.
public int compareTo(Object o) {
CallSite[] var2 = $getCallSiteArray();
return ScriptBytecodeAdapter.compareTo(this.priority, var2[0].callGroovyObjectGetProperty((ConsoleRow)ScriptBytecodeAdapter.castToType(o, ConsoleRow.class)));
}
I tried following this guide and code structure when doing moving the code to a library
https://docs.gradle.org/current/samples/sample_building_groovy_libraries.html
Thanks for any feedback
p.s: My code might look weird, I tried first to have everything with the def blablabla but I was having some issues with typecasting but I don't think this would be the reason for the problem I'm facing.
Anyway I got a look at the generated code in my IDE and I see a lot of get methods just no idea where they expected this getProperty from
Ok this was definitely a user error.
I am using distribution version of gradle 6.5.1
When I did the gradle init to bootstrap my project I was provided with the dependency of gradle groovy-all version 2.5.11
implementation group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.5.11'
I thought that was a mistake and just updated to the latest version.
implementation group: 'org.codehaus.groovy', name: 'groovy-all', version: '3.0.9'
Now the problem is that the project in which I'm using the library is also running with gradle 6.5.1 so probably this version missmatch between compiple and usage was causing the problem.
By reverting to the correct version suggested by gradle the problem is gone.
I have been developing Xamarin since XF 1.0. Memory leak was a huge problem from XF 1.0 till now XF 2.4. I have always been implementing Dispose Pattern in all my ContentPage and ViewModel classes to make sure Event handlers, Message Subscribers, object references are all removed and set to null either in OnDisappearing() or in Dispose() function of each class.
Here is something very intriguing. After I upgraded my project to Xamarin.Forms 2.4.0.280 from 2.3.3.180. I found out this type of code that used to create memory leak in Xamarin.iOS no longer occur.
Code Example:
public partial class ContactUsPage : ContentPage
{
public ContactUsPage ()
{
InitializeComponent ();
}
protected override void OnAppearing ()
{
//Lets say I have button named "btn" declared in Xaml page
btn.Clicked += OnButtonClicked
MessagingCenter.Subscribe<CoreMessenger, string>(this, "AMessageType", (sender, arg) =>
{
//some code
});
}
protected override void OnDisappearing ()
{
//btn.Clicked -= OnButtonClicked
//MessagingCenter.Unsubscribe<CoreMessenger, string>(this, "AMessageType");
}
}
Prior to Xamarin.Forms 2.4, If we Push and Pop this page as a Modal multiple time, we will see multiple instances of this page persist in memory and will never be Garbage Collected due to Event Handler and Subscriber are not removed and they created object references pointing back to the ContactUsPage instances, unless we uncomment the code in OnDisappearing () function.
The above code no longer creates memory leak in Xamarin iOS when compiled in Xamarin.Forms 2.4.0.280, although it is clearly leaking memory according to my knowledge of how reference counting garbage collection works. Did Xamarin change the GC method for Xamarin.iOS? So it is doing mark-and-sweep like Xamarin.Android now?
Can someone tell me what changed and why?
Thanks a ton!
Have a look at the commit history for the MessagingCenter.
https://github.com/xamarin/Xamarin.Forms/commits/master/Xamarin.Forms.Core/MessagingCenter.cs
I believe you are seeing the effects of the commit on Jan 03, 2017. At least in terms of your example above using MessagingCenter.
With a skeleton project with FirstView from HotTuna package, and with Build linker behavior set to "Link all assemblies", I get the following error:
System.MissingMethodException: Default constructor not found for type Cirrious.CrossCore.IoC.MvxPropertyInjector
Using NuGet package v3.1.1 for all MvvmCross (4 packages)
LinkerPleaseInclude file does have the line
[MonoTouch.Foundation.Preserve(AllMembers = true)]
Using the latest stable build:
On PC:
Xamarin for VS 1.12.278
Xamarin.iOS 1.12.278
Mac:
Xamarin.iOS 7.2.2.2
Of course with Linker behavior of SDK only, it runs fine. Any suggestions anyone?
Solved; So, with the basic project, there were three consecutive errors in the following order:
System.MissingMethodException: Default constructor not found for type Cirrious.CrossCore.IoC.MvxPropertyInjector
can be resolved either by --linkskip=Cirrious.Core (ugly), or by including the following in LinkerPleaseInclude.cs
public void Include(MvxPropertyInjector injector){
injector = new MvxPropertyInjector ();
}
Next error is:
Cirrious.CrossCore.Exceptions.MvxException: Failed to construct and initialize ViewModel for type {0} from locator MvxDefaultViewModelLocator - check MvxTrace for more information
This one is difficult; Simple fix is to ofcourse to do a --linkskip=portableLibrary, or to crate an instance of the ViewModel somewhere (perhaps in LinkerPleaseInclude.cs); problem with the second approach at-least in my case is, most of my VM doesn't have a parameter less constructor, and obviously using IOC in this case wouldn't help.
Final Error:
System.ArgumentNullException: missing source event info in MvxWeakEventSubscription
Parameter name: sourceEventInfo
Either use --linkskip=System (ugly), or add the following to LinkerPleaseInclude.cs
public void Include(INotifyPropertyChanged changed)
{
changed.PropertyChanged += (sender, e) => {
var test = e.PropertyName;
};
}
This was enough for my basic project to run with LinkAllAssemblies, Using LLVM optimizer, and Use SGen collector.
Hope this will help anyone looking for a solution.
I hit this when my XCode was out of sync with the latest Xamarin on my Mac. Upgrading XCode to the latest resolved the problem.
I recently upgraded my operating system from Windows XP to Windows 7 SP1 64 bit. We are using Visual Studio 2008 Professional Edition and Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production.
When I try to execute this code I am getting the below exceptions
try
{
CDatabase *pDatabase = CDatabaseConnection::getDatabaseConnectionProcessLog();
ORSProcessLog rsProcessLog(pDatabase);
CString strFilter = _T("SELECT PROCESS_ID, MESSAGE FROM OP_PROCESS_LOG");
rsProcessLog.SetRowsetSize(1);
if( !rsProcessLog.Open(CRecordset::dynaset, strFilter, CRecordset::appendOnly) )
return;
if( !rsProcessLog.CanAppend() )
return;
rsProcessLog.AddNew();
rsProcessLog.m_PROCESS_ID = gcsProcessID;
rsProcessLog.m_MESSAGE = csMessageA;
rsProcessLog.Update();
rsProcessLog.Close();
}
catch ( CDBException* pEx )
{
bException = true;
pEx->GetErrorMessage(szCause, 255);
}
catch( CException* pEx )
{
bException = true;
pEx->GetErrorMessage(szCause, 255);
}
where rsProcessLog is the CRecordset object using a successfully connected database pointer pDatabase
In 32- bit Debug version I get a message box at rsProcessLog.Close(); with the below text
Debug Error
Program: ......\Test.exe
HEAP CORRUPTION DETECTED: after Normal block (#506) at 0x0087F628. CRT detected that the application wrote to memory after end of heap buffer.
Memory allocated at f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dbcore.cpp(2626)
(Please Retry to debug the application)
In 32- bit Release version I get a message box at rsProcessLog.Close(); with the below text
Windows has triggered a breakpoint in Test.exe
This may be due to a corruption of the heap, which indicates a bug in Test.exe or any of the DLLS it has loaded.
This may also be due to the user pressing F12 while Test.exe has focus.
The output window may have more diagnostic information.
The above code was a working code in Windows XP with the rest of the env remaining the same and it continues to run in Windows XP but not in Windows 7. Any help will be greatly appreciated.
After some analysis of MFC CRecordest class I noticed that the problem appears after call to ::SqlSetPos where m_rgRowStatus array allocated on the heap become damaged (one byte more is written on the heap).
First and clean approach to problem is to force CRecordset class to use update/delete SQL statements instead of ::SqlSetPos function. To achive this you need to open your database using OpenEx method with CDatabase::userCursorLib option.
CDatabase db;
db.OpenEx(ConnectionString, CDatabase:useCursorLib);
This will change some CRecordset functionalities. See more at: http://msdn.microsoft.com/en-us/library/c689y99f.aspx
Second approach (dirty) is to reallocate m_rgRowStatus field, to use more memory on the heap, so call to ::SqlSetPos will not write to unallocated memory.
One way to do that is to override CRecordset::PreBindFields function:
void CMyDerivedRecordset::PreBindFields()
{
if ( ! (m_dwOptions & useMultiRowFetch) )
{
delete [] m_rgRowStatus;
m_rgRowStatus = new WORD[2];
}
CRecordset::PreBindFields();
}
You can do that in all of your CRecordset derived classes, or you can make one new CRecordset derived class which will become base class for all of your existing CRecordsetderived classes.
We have a RC module that gets dropped into our cloud servers during hot deployment. To that end, I need a way to flush the DNS programmatically from within JAVA. The best solution that I can think of is to just have java fire an external shell script, however I'm not having any luck. I've tried the "normal" procedures to an avail:
1) restarting nscd service (not installed in these servers)
2) /etc/init.d/networking restart (no effect)
3) /etc/init.d/dns-clean start (no effect)
Anyone have any more suggestions?
(NOTE: this is a re-word of a previous post that must have been determined as being "non-development" related...)
TIA
This is JVM implementation dependent. On Oracle JDK, you need to set the networkaddress.cache.ttl and networkaddress.cache.negative.ttl security properties (in $JAVA_HOME/lib/security/java.security). The factory default is to cache positive answers forever.
AFAIK there is no way to flush the cache at runtime.
See http://docs.oracle.com/javase/7/docs/technotes/guides/net/properties.html
Since Java 6 (Sun/Apple) and Java 7+ (OpenJDK), the default value for networkaddress.cache.ttl is 30 seconds (specified in sun.net.InetAddressCachePolicy) assuming there is no security manager installed (via -Djava.security.manager or System.setSecurityManager).
Meanwhile, the default value for networkaddress.cache.negative.ttl is 10 seconds (specified in $JRE_HOME/lib/security/java.security).
Web servers (e.g. Tomcat) may install a security manager on startup, in which case the JVM (at least those I've mentioned) will cache positive lookups forever by default.
You'll need to natively call (JNI) to res_init() from Java:
ResInitLoader.java
package my.pkg;
public class ResInitLoader {
static {
System.loadLibrary("ResInit");
}
public static native int resInit();
}
ResInit.c
#include <resolv.h>
JNIEXPORT jint JNICALL Java_my_pkg_ResInitLoader_resInit (JNIEnv *env, jclass clazz) {
return res_init();
}